std.getopt suggestion

foobar foo at bar.com
Thu Sep 29 15:01:49 PDT 2011


Andrei Alexandrescu Wrote:

> On 9/29/11 11:18 AM, Jonathan M Davis wrote:
> > On Thursday, September 29, 2011 08:41 Andrei Alexandrescu wrote:
> >> The proposed change adds net negative value. It forces people to create
> >> an object in order to call a simple function, for the vague benefit of
> >> tenuous corner cases.
> >
> > I specifically suggested that there still be a free getopt function which
> > wraps the call to GetOpt.init. So, for most people, there would be no cost to
> > having a struct to hold the configuration options. Yes, if I were suggesting
> > that everyone be forced to create a an object to call getopt, that would be
> > definite net negative change, making the average user of std.getopt pay for
> > improving a rare use case. But I'm not suggesting that. And if people think
> > that it's better to have a GetOpt struct (or whatever you want to call it; the
> > name isn't all that important to me - GetOptConfig?) which is passed to
> > getOpt, then that's fine too. It just seems simpler to me to make getOpt a
> > member function, so I suggested that. The main point was that it's more poorly
> > encapsulated to have the mutable variables free in the module, it breaks
> > purity, and while it might work fine for std.getopt since it's really only
> > doing one thing, it's still generally bad design to put mutable variables at
> > module scope, so it looks bad to a lot of programmers, and there's no real
> > cost that I see to having them in a struct.
> 
> We won't be able to please everyone. That being said, the current design 
> is sound. http://c2.com/cgi/wiki?MonostatePattern
> 
> > So, if the issue is that getOpt is a member function on a struct rather than
> > taking the struct, then we can have it take the struct. And on the whole, I do
> > think that std.getopt works great and has a solid design. But I don't
> > understand why you would ever have mutable globals. They don't really buy you
> > anything. With the struct, worst case, you create it and pass it to the getOpt
> > call, and it adds one line of code for constructing the type before setting
> > the value.
> >
> > GetOptConfig config;
> > config.endOfOptions = "@";
> > getOpt(args, config, ...);
> >
> > And if you construct it and pass it directly, it could _save_ you a line of
> > code. It also better enables those _rare_ cases where you actually want to
> > call getOpt twice as well as make it possible for getOpt to be pure for those
> > rare cases where that might matter - all at no cost to 99.99% of the uses of
> > getOpt.
> 
> The cost is there in the documentation, examples, etc. etc.
> 
> Here's the baseline:
> 
> "In order to get a command-line options for your program, you must 
> import std.getopt, define the variables holding the options, and call a 
> function to fill them."
> 
> This is the baseline. We don't need to motivate the baseline. Everything 
> adding to the baseline must be motivated.
> 
> >> I kindly suggest we stop the isometric workout and look into adding good
> >> value to Phobos.
> >
> > Someone else has been working on improving some of the guts of getopt. I was
> > merely pointing out a place that it could be further improved as part of that.
> > The extra work would be minimal and give a net improvement IMHO, and if the
> > defaults are changed at all (which there is some reason to do due to a new
> > value in the config enum) or if getopt is changed to getOpt to follow the
> > naming convention, then we'd be making a change anyway. So, this small change
> > that I'm suggesting wouldn't really create any issues or affect much code at
> > all. It would just improve the basic module design.
> 
> I don't think it would improve the module design, even without 
> considering cost of change. It just adds useless clutter.
> 
> 
> Andrei

I just read through the above link provided by Andrei. I have a few notes/questions:
a. The article states that this is an evil pattern.
b. The examples are using a struct/namespace to encapsulate the data as suggested by Jonathan. 
c.  Using global variables causes two main problems, non of which you acknowledged: 
    1. Name pollution - Yes, it is solvable in D with renamed imports and such but is still annoying. 
    2. MT / purity. Are these variables marked 'shared'?  If yes, then access to them needs to be properly synchronized.
        If no, than the assertion regarding a single state is false as there would be a separate state for each thread. 
Does getopt (btw, awful name) handle any of these issues? 
 


More information about the Digitalmars-d mailing list