Boost logo

Boost :

From: Rozental, Gennadiy (gennadiy.rozental_at_[hidden])
Date: 2003-05-27 15:29:42


>> > 2. Layered design.

> > IMO All of my
> > concerns are unfortunate consequences of the way you designed your
> > library. IMO there should be one typed storage for the parsed
> arguments
> > (instead of 3 like you have) linked with formal parameters
description.

> You are not correct. There are two storage mechanism for parsed data.
> First
> ('options_and_arguments') stores *only* strings. Second
> ('variables_map')
> stores typed values. So, there's one typed storage.

1. You store something inside class cmdline
2. You store strings in options_and_arguments
3. You store typed values in variables_map

In my opinion 2 places are redundant. You should only have one.

> > Plus second layer managing composition of parameter originated by
> > different sources.

> That's 'variables_map'.

But variables map is part of first layer, it's store typed arguments. And it
almost
does not have any functionality I expect to see on this second layer
dedicated to combinind parameters from different sources.

> >> > b. Force same style for all parameters in command line (I could
>not
>>> > define /h --my_long_param)
>>>
>>> Do you need it in practice?
>>
>> Why not. Maybe different modules require parameters in different
>style.
>
>I feel this to be artifical example, and would not be surprised if no
>user
>of program_options will ever want it. And if it wants... custom parsers
>can be used.

But this is part of functionaly you supply out of the box. And now i need ot
rewrite it.
You keep repeating: "use custom parser". I wonder why would I need this
framework then.

>>> desc.add_options()
>>> // first argument is options name
>>> // second argument is parameter name
>>> // third argument is description
>>> ("output", "file", "output file")
>>> ....
>>> ;
>>>
>>> This means that one comment line is added for first argument, and
>then
>>> you can very conveniently specify option name.
>>
>> Poor maintenance programmer looked on this code and spread hands
>puzzled:
>> What is option name and what is parameter name???? Which one should I
>use
>> to identify argument? Where the value assigned? What is default value?
>
>Sorry, but this kind of questions can be answered only in docs.

Sorry. But this is not good enough for me.

In my terms above would look like this:

    parameter<std::string>( "output" )
      << place_to( output_file_name )
      << default_value( "/tmp/abc" )
      << description( "output file name" )

You do not need to know anything in addition about how parser works.
Moreover it's unifies and easily extendable to adopt different modifers.

>> class cmdline access methods:
>> option_name()
>> option_index()
>> raw_option_name();
>> option_value();
>> option_values();
>> argument();
>> arguments();
>>
>> You obviously struggle from need to provide on one hand container
>> interface, on the other iterator one.
>> Plus instead of N methods returning
>> properties of option there should be one that returns foe example
>'option'
>> structure.

>... which 'option' structure would contain the same set of methods?
>Let's
>consider the needs of 'cmdline' clients. You have

> cmdline cmd(....);
> while(++cmd) {
> if (cmd.at_option()) {
> ...
> }
> }
>
>With iterators, that would become
>
> for(cmdline_iterator i(...), e; i != e; ++i) {
> if (i->is_option()) {
>
>
>Wait! Again, what's 'value_type'. Some imaginary 'option_or_argument'
>class?
>boost::variant? boost::any? Yep, that would be an interator, but you
>gain
>nothing. It will be only input iterator, and with such a specialized
>'value_type', that to use that iterator, you need to known that you're
>dealing with command line --- there's no place for genericity.
>
>I'd probably buy your argument if you'd say that one can devise class
>'option' and make command line parser, config file parser and something
>else parser iterator, with 'option' as the value type. That would be
>nice,
>but it can't be done. cmdline has addition 'raw_option_name' member
>function, and config_file cannot return arguments. The interfaces are a
>bit
>different.

In my design I provide rnadom access iterator to the storage of parsed
arguments of
type cla::argument. And I could use whatever generic algorithm I like with
it.

Why does anybody need raw_option_name()?

Also it's beyond my understanding why we need at_option, at_argument. May be
it's because I still could not get what meaning you use for these terms in
this context.
 I parsed argc/argv, stored typed argument. Now I only need ot get the value
out of argument I identifued somehow (by name, or index, or order -
whatever)

> my_prog --service name=>Repository ...
>
> Here parameter name is service name, separator is string "=>", value
is
> 'Repository'.

> Nope. It's not supported by cmdline class.

And you would not be able to support it within the bounds of your design.

>> > 9. Multi-pass parsing support
> If that's not sufficient (which I doubt), I can think of a more general
> solution. Basically, 'cmdline' class can allow unregistered options.
> With
> a bit of tweaking, it can return unparsed tokens.

There is a solution. But it's not trivial. And not in a bound ot your
current design.

>> If you're use error codes, you'd have
>> to check it after calling each function.
>
> No. I would not. In majority of the cases I do not bother whether any
> intermediate step fails, parsing or validation fails. Whatever
happened
> during CLA declaration, parsing and validation I just want to get a
> notification about an error during CLA parsing procedure and have and
> access to the error message. IOW it would look like this:
>
> > cla::parser p;
> > p << parameter<int>( "name" )
> > ....
> > if( ! p.parse(argc,argv) ) {
> > cout << p.error_msg() << endl;
> > p.usage();
> > return 1;
> > }
>
> I don't see here handling of response files or config files... if you
> were
> to add it, would you write the same "if" block a couple of times?

I may have several if spatements:
    if( cla_parser.parse(...) ) ...
    if( config_file.parse(...) ) ...
    ...

It's not worse than several catch clauses. Try/catch seems redundant when
used right aroung the function that throw an exception.

>> > Moreover in many interfaces library assumes existence on long
name,
>> > short
>> > name, which may not be the case even with name based parameter
>> > identification.
>>
>> I don't understand what you mean here.
>
> > I may not have long name, but only short one, like with old getopt
> had.

> It's not a problem. You'd still use the long name for identification
> purposes, but disable long names in command line.

I don't get it. What long name would I use if it only have short name.

> > I may not have short name but only long one, like the style I am
> > personally prefer.

> What's problem with this case? It's supported out-of-box.

What would you return when user call short name method?

>> > 15. External parsers support.
> > I do not want to store parsed values inside the parser at all. Instead
> I
> > want to register for every parameter callback function.

> That's another example I don't see any use for. What will those callback
> functions do. Can you given some more details why it might be needed?

Let say I have method set_trace_level that manage tracing level for you
application.
What I need is in my terms look like this:
   parameter<int>( "trace_level" )
      << default_value( 0 )
      << handler( set_trace_level )
      << description( "specifies the trace level for the application" )

Now when argc/argv parsed argument value is not stored into list of parsed
argument. Instead
handler function call and parsed value passed.

I may have different parsers for all my parameters.

> - Volodya

Gennadiy.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk