Boost logo

Boost :

From: Gennadiy Rozental (gennadiy.rozental_at_[hidden])
Date: 2004-11-23 13:00:53


"Doug Gregor" <dgregor_at_[hidden]> wrote in message
news:0BBD3222-3D6E-11D9-9E8D-000A95B0EC64_at_cs.indiana.edu...
> On Nov 23, 2004, at 9:37 AM, Gennadiy Rozental wrote:
> > "Doug Gregor" <dgregor_at_[hidden]> wrote in message
> > 1. It really trivial to implement the restriction on public level:
>
> Ok.

Does this mean that you agree that submitted library does not provide
"more-capable" interface?

> >> Granted, your typed_keyword permits earlier detection of certain
> >> typing
> >> errors. For instance, if I try to write "name = 5", your library will
> >> abort the compilation at that expression but the library under review
> >> will instead remove "f" from the overload set if it is called.
> >> However,
> >> there is a potential price to be paid for this earlier checking: the
> >> name "name" has now been reserved for string parameters and cannot be
> >> reused without introducing a new "name" keyword in some other scope
> >> with a different type.
> >
> > 1. That is not true. Nothing prevent me from introduction of keyword
> > name in
> > different namespace/compilation unit. Actually in most cases I use
> > keywords
> > with namespace qualifiers: sock::name, cla::name, factory::name e.t.c.
>
> Precisely why I wrote "in some other scope", which refers both to
> different namespaces and different translation units :)

My point is why should I reuse? No, even you shouldn't without real reason..

> > 3. IMO It's bad idea to introduce global keywords used by various
> > independent functions for different purposes and different data types.
> > For
> > example:
> >
> > new window( size = make_pair(10,20) );
> > new listbox( size = 10 );
> > new Jeans( size = "36x30" );
> > new Bowl( size = 5.675 );
> >
> > I don't see above as a good practice and library shouldn't encourage
> > it.
> > Instead one should either use difference namespaces (see 1) or
> > different
> > keywords: dimensions, size, cloth_size, volume.
>
> Why is a listbox so important that it gets the short name "size"
> whereas the jeans get the longer name "cloth_size"? The example is
> good, but I don't think it strengthens your position at all. On the
> contrary, we see that "size" means very different things when talking
> about listboxes vs. when talking about jeans, but the word is not
> ambiguous in the context of each line.

I believe my position in regards to parameter type is very simple. In legacy
C++ we write:

void foo( char const* name, int size );
void goo( char const* name, int size );

Function parameter entity has 3 unique "properties":

1. scope. defined by function name
2. name. Well, the name.
3. type. C++ enforce strict type checking.

I believe "named parameters" solution should have the similar
characteristics. Even though above function both have the same type and name
it still two essentially different things. If we convert above functions to
named parameter interface we should introduce scopes f and g (this is an
extreme, but keep reading) and
calls would look like:

foo( foo::name = "abc" );
goo( goo::size = 5 );

Now in practice foo and goo probably belong to some namespaces aaa and bbb.
Accordingly keywords may belong to respective namespaces and calls would
look like:

aaa::foo( aaa::name = "abc" );

or if we have using namespace bbb;
goo( size = 5 );

The only exclusions where we may share the keywords are cases with series of
related function. For example different constructors for the same class or
different access methods within same class e.t.c.

If we have keyword as a standalone entity, separated from function, this
will bring following issues:

1. Where this keyword is defined? So that it could be reused by anybody who
need 'size' parameter?
2. If we both defined keyword 'size' and both are reusable which one should
Joe programmer should use?
3. Each function that uses this keyword need to repeat type checking.
4. Function may have two different size parameters, where should I use
global size keyword and should I introduce my own for second one?

All of that is escalated by what submitted solution propose in regards to
type enforcing:

struct f_keywords : keywords<
              named_param<
                 name_t
               , boost::mpl::false_
               , boost::is_convertible<boost::mpl::_, std::string>

This interface is way too verbose IMO for the basic, but most widely needed,
type enforcing feature.

> >> My (subjective) expectation is that a library
> >> may start by using typed keywords, but as the library evolves and more
> >> functions gain named parameters I'd expected those typed keywords to
> >> become non-typed keywords. There is no place in the BGL, for instance,
> >> where I would consider using a typed keyword.
> >
> > That Ok. Unfortunately I am not that familiar with library but I do not
> > believe BGL is the best example. BGL is template based library
> > solution. In
> > an end user's code my expectation is that in most cases one would use
> > typed
> > keywords.
>
> The BGL is _an_ example, but clearly not the only one. However, it does
> have the advantage of having had a named parameters mechanism for the
> last several years, so in my mind it carries significant weight
> relative to hypothetical usage scenarios.

The BGL is an example that uses typeless keywords (obviously because it's
highly templated library). In my experience I had numerous other examples
that used typed keywords. My position that for regular (non-template
function) one would prefer typed keyword.

> >> Another subjective difference between the two is in the call to "f".
> >> The library under review supports the syntax:
> >>
> >> f(name = "wibble", value = int);
> >>
> >> whereas, as I understand it, your library supports the syntax:
> >>
> >> f((name = "wibble", value = int));
> >>
> >> I'm not going to weigh in on this issue.
> >
> > Submitted library allow both syntaxes. I would never use first though.
> > In my
> > experience named parameters interface is most valuable facing numerous
> > optional function arguments. Why would I want to provide 10 overloads
> > for
> > the same functions with different number of arguments, where 1
> > suffices?
>
> You are asking the wrong question. The right question is "which syntax
> is better for users?" Step back from the implementation, the language,
> and the limitations of both and determine what syntax you would like to
> use when calling these functions. Implementation details are secondary
> to interface details.

This maybe the case would we were discussing named parameter feature for
inclusion into language support. As it stands now, until we have template
functions with variable length parameters list, the only viable option (IOW
best for the user) IMO is single function interface. In theory I still would
prefer single function interface:

template<typename T[]>
void foo( T[] const& params ) {
    std::cout << params[name] << params[value];
}

> Doug

 Gennadiy


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