
"Doug Gregor" <dgregor@cs.indiana.edu> wrote in message news:0BBD3222-3D6E-11D9-9E8D-000A95B0EC64@cs.indiana.edu...
On Nov 23, 2004, at 9:37 AM, Gennadiy Rozental wrote:
"Doug Gregor" <dgregor@cs.indiana.edu> 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