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?