Am I reading this wrong, or is std.getopt *really* this stupid?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sat Mar 24 00:05:30 UTC 2018


On Friday, March 23, 2018 16:29:48 H. S. Teoh via Digitalmars-d wrote:
> I just ran into this seemingly small problem:
>
>   void main(string[] args) {
>       string[] searchPaths;
>       getopt(args,
>           "l", (string opt, string arg) {
>               // searches through searchPaths
>               openFile(arg);
>           },
>           "I", (string opt, string arg) {
>               searchPaths ~= arg;
>           },
>           ...
>       );
>   }
>
> Running the program with:
>
>   program -I /path/to -l myfile
>
> causes a runtime error that 'myfile' cannot be found, even though it
> actually exists in /path/to/*.  I thought it was odd, since obviously
> the -I is parsed before the -l, so searchPaths should already be set
> when -l is seen, right?
>
> Well, looking at the implementation of std.getopt turned up the
> disturbing fact that the program's argument list is actually scanned
> *multiple times*, one for each possible option(!).  Besides the bogonity
> that whether or not searchPaths will be set prior to finding -l depends
> on the order of arguments passed to getopt(), this also represents an
> O(n*m) complexity in scanning program arguments, where n = number of
> arguments and m = number of possible options.
>
> And this is not to mention the fact that getoptImpl is *recursive
> template*.  Why, oh why?
>
> Am I the only one who thinks the current implementation of getopt() is
> really stupid??  Can somebody please talk some sense into me, or point
> out something really obvious that I'm missing?

Well, to be fair, getopt is called once in the entire program, and it's
abnormal for there to be very many arguments, so the big-O complexity likely
isn't going to matter. I'm fairly sure that a lot more has gone into having
getopt be highly functional than has gone into making it efficient.

If you can improve its performance without breaking anything, then great,
but having it be a bit slow really isn't likely to matter much.

Now, if you're passing lambdas to it (which I didn't even know was
possible), then having the arguments called multiple times probably is a
problem and should probably be looked into. I suspect that that
functionality was added later, and the getopt's design as a whole didn't
necessarily take it into account. Remember that getopt has been around a
while and had a fair bit bolted onto it over time. Sometimes, adding what
seems like a minimal addition to existing functionality can have unintended
consequences when it interacts with other stuff, and with how complex getopt
is, it's not entirely surprising if it has some problems. I've found that it
works fairly well overall, but I think that I've also mostly stuck to the
functionality that it started with.

- Jonathan M Davis



More information about the Digitalmars-d mailing list