Boost logo

Boost :

From: Oleg Abrosimov (beholder_at_[hidden])
Date: 2006-09-27 12:55:24


David Abrahams writes:
> Oleg Abrosimov <beholder_at_[hidden]> writes:
>
>> Hello David,
>>
>> As a result of this discussion I've read boost::parameter docs
>> completely. And now I want to apologize for my aggressive post. This
>> library is very sophisticated.
>> Nevertheless, I didn't become it's proponent and there are some thoughts
>> about the overall function parameters problem that can be useful for
>> this discussion:
>>
>> 1) parameter's type is not a panacea
>>
>> It means that giving function parameters unique types can solve the
>> problem of mistakenly swapping them, but is not always applicable,
>> sometimes impractical,
>
> If you're referring to deduced parameters
> (http://tinyurl.com/mayug#deduced-function-parameters), of course it's
> not a panacea. That's why the library supports named parameters.

Yes, it is exactly what I mean.

>
>> doesn't solve problem with optional parameters, etc.
>
> I don't know what problem you're referring to, but deduced parameters,
> where applicable, certainly do solve the main problem with optional
> parameters (spurious order dependencies).

Yes, but note the "where applicable" constrain. When I speak "doesn't
solve" I mean that it can not be used to solve the problem in all cases,
only "where applicable".

>
>> 2) many parameters:
>> - some are mandatory and
>> - some are optional with default values supplied
>>
>> It means that both optional and required parameters should be taken into
>> account.
>
> Both optional and required parameters are taken into account by the
> Parameter library. What documentation did you read that made you
> think they weren't?

You are excited a bit, dissipate your energy, please. Here I'm
formulating my requirements for parameter lib that would be good for me.
Of course boost::parameter support it!

>
>> Definition:
>> configuration - is a set of parameters for a given function
>> f1(configuration);
>>
>> Requirements for ideal solution of implementing and using function's
>> configurations:
>> 1) simple implementation of configuration and function that uses it
>> 2) maximum maintainability
>> it means:
>> a) configuration parameters should be specified as close to
>> function call as possible
>> b) configuration parameters should be visible (names)
>> c) configuration reuse
>>
>> solutions:
>> 1) positional function parameters
>> + mandatory parameters
>> + optional parameters
>> - invisible parameters
>
> ??

consider
foo(1, 2);
// reader have no glue about what parameters mean
// I call it invisible parameters

foo(width = 2, height = 1);
// boost::parameter - visible

>
>> - interference of optional parameters complicates its usage
>> - reuse is not possible
>> + no ambiguity with other language constructs
>> + implementation is simple
>>
>> 2) named parameters
>> + mandatory parameters
>> + optional parameters
>> + visible parameters
>> - reuse is not possible (it is not _very_ important, but important. Is
>> there a way to extend parameter lib to support such a reuse?)
>
> You're not saying what you mean by "reuse." We think reuse is very
> possible with the Parameter library, so it's quite unclear what you
> might be referring to.

libraries are all about reuse. boost::parameter is not an exception of
course.
By reuse I mean configuration reuse in client code. Not reuse of
boost::parameter library in other libs.
Consider:
foo(width = 2, height = 1);
// ... some code ...
foo(width = 2, height = 3);

vs.

TFooParam p;
p.width = 2;
p.height = 1;
foo(p);
// ... some code ...
p.height = 3;
foo(p);
// p is reused here

The drawback in such a scenario is reduced visibility, because of 'p'
can be initialized too far from the second call of 'foo'.
But in practice most common scenario is to initialize 'p', call
'foo(p)', then modify 'p' slightly and call 'foo(p)' again. It means
that visibility is preserved.

>
>> - ambiguity with other language constructs
>> (it is very important drawback. As I realized from parameter docs,
>
> You're not being specific enough here either. I can't imagine what
> ambiguity you mean.

consider:

void new_window(char const* const, int = 10, bool = true);

int main()
{
     int width;
     bool titlebar;
     new_window("alert", width=10, titlebar=false);
     return 0;
}

call to new_window can not be translated unambiguously by reader in
presence of named params. I expect that compiler will complain, but
reader can be fooled by such a call, especially if we change it a bit:

int main()
{
     new_window("alert", width=10, titlebar=false);
     return 0;
}

What is a 'width' here? parameter name? or some variable in global scope?

>
>> great effort should be made to make such an ambiguity possible. It would
>> be better IMO to eliminate this efforts in implementation and the
>> ambiguity in one shot - provide special may be auxiliary structure -
>> like syntax to use parameters)
>
> It's unclear what you mean.

I mean that significant amount of work should be done to allow named
parameter syntax that can be ambiguous as was shown above. The idea I
was trying to explain is simple - May be it is possible to find a way to
achieve both goals - unambiguity and reduce of efforts required to
enable named params usage.

>
>> - implementation is not simple
>> (really. all this nightmare can be done for library that is created
>> once and used many times, but I need a tool that can be used on a daily
>> basis for ordinary code.
>
> One can use Boost.Parameter for ordinary code on a daily basis. We
> (Boost Consulting) have done it for our major customers and they are
> *very* satisfied with the results.
>
>> it means that simplicity of an implementation
>> should be very close to the solution with auxiliary structures below)
>
> IMO the implementation complexity doesn't matter as long as it works
> and gives comprehensible feedback when misused. Do you inspect the
> source code of your compiler and complain about its implementation
> complexity?

We are living in very different worlds. and it is good for you. I'd be
happy if I can say the same as you've said here.
Not many of as are paid for libraries writing. My job is application
programming. It is always done in a high time pressure.

I'm writing several functions per day. Most of them are used only by me
to implement other functions. I _can not_ spend time to implement named
params for each function that I wrote. It is completely impractical. But
I want to have as little amount of bugs in my code as possible. that is
why I'm looking for solution that can give me a great amount of safety
and be easy to implement for each of a ~10 functions that I wrote per day.

The auxiliary struct solution is a good compromise for me and till now I
have no problems with it. But this from discussion I learned that it has
some drawbacks with the most important for me - inability to specify
required parameters at compile time. Now I'm trying to get some ideas
from boost community to workaround it somehow.

>
>> 3) auxiliary structures
>> - mandatory parameters
>> + optional parameters
>> + visible parameters
>> + reuse is possible
>> + no ambiguity with other language constructs
>> + implementation is simple
>>
>> The last approach with auxiliary structures has only one drawback - it
>> is not possible to have required parameters with it. May be you, David,
>> can see a way how parameter lib can be reused/extended into something
>> like the las solution, but with all '+' marks?
>
> No, and it has more drawbacks. Go back and read the Parameter library
> review commentary if you want to find all of them.
>
>> ( I remember additional arguments by Michael Walter:
>>
>> a) parameter values are copied
>> b) parameter values need to be default-constructable (into a valid state)
>>
>> but they are not important for me just now
>> )
>
> Well, those are two of the drawbacks, and they count (maybe not for
> you, but they do count).
>
>> May be the best solution that we can have now is:
>>
>> //implementation:
>> BOOST_PARAM_STRUCT_BEGIN(TFuncParams)
>> BOOST_DECLARE_PARAM_OPTIONAL(type1, name1, def_val1)
>> BOOST_DECLARE_PARAM_REQIRED(type2, name2)
>> BOOST_DECLARE_PARAM_OPTIONAL(type3, name3, def_val3)
>> BOOST_DECLARE_PARAM_OPTIONAL(type4, name4, def_val4)
>> BOOST_PARAM_STRUCT_END()
>
> That's not a nightmare?

It is ugly. Yes. but it is easy to write, remember and understand.
Better syntax is welcome

>
>> void func(TFuncParams const& params)
>> {
>> cout << params.name1;
>> // etc.
>> }
>>
>> usage:
>> BOOST_INSTANCIATE_PARAM_STRUCT_BEGIN(TFuncParams, params)
>> BOOST_PARAM_OPTIONAL(params, name1, val1)
>> BOOST_PARAM_REQIRED(params, name2, val2)
>> BOOST_INSTANCIATE_PARAM_STRUCT_END()
>>
>> func(params);
>>
>>
>> The idea is that all boost::parameter magic is hidden by those macroses.
>> The question is - can it be really done?
>
> I don't know. The above meets few if any of my requirements for such
> a library, so determining feasibility will have to fall to someone else.
>

Anyway, thank you for your attention and reply.

Oleg Abrosimov.


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