Boost logo

Boost :

From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2008-04-02 16:36:48


On Wed, Apr 2, 2008 at 9:28 PM, shunsuke <pstade.mb_at_[hidden]> wrote:
> Giovanni Piero Deretta wrote:
> > On Wed, Apr 2, 2008 at 6:40 PM, shunsuke <pstade.mb_at_[hidden]> wrote:
> >> Giovanni Piero Deretta wrote:
> >> > I'm not saying that egg should support optionally-lazy functions [1],
> >> > it is ok if the lazy and non lazy variant have the same name. I just
> >> > want to be sure it is easy to define them.
> >>
> >> I did't adopt "optionally-lazy" functions.
> >> As you show, many functions take FunctionObjects as arguments
> >> so that protect or unlambda is needed everywhere.
> >
> > Well, as I said, the lambda[] really helps to make lambdas stand up in
> > function calls. Also you have to wrap lambdas in 'regular' in may
> > calls anyway so you might as wel just use lambda[]. After a while it
> > becomes second nature, I simply use it even if it isn't strictly
> > required.
>
> I don't sure what lambda[] does.

protect + regular basically. (or only regular if it already works as protect).

> Why not call bll::unlambda?

I need 'regular' behaviour. Also the name is longer :), and I really
like the square bracket syntax.

When/if boost.lambda will be unified with phoenix, I'll use phoenix
'lambda' (which has exactly the same syntax plus optional support for
local variables).

> BTW, `regular` incurs a slight overhead, so that
> I didn't adopt automatic "regular"ization in Oven.

Ok. I've never used lambda in performance critical code, so I can't
say. I prefer to play it safe and always regularize my lambdas.

>
> >> (I always follow the rationale "one name, one functionality".)
> >
> > With real lambda abstraction, you wouldn't need a different name to
> > call a function inside a lambda expression. I was trying to
> > approximate it as much as possible in c++.
>
> But real lambda abstraction introduces different syntax.

Of course.

>
>
> >> >> After all, Boost.Lambda bind and placeholders are not usable here.
> >> >
> >> > Why? Detail please :)
> >>
> >> A functional call of `static_< always<F> >::type`
> >> is expanded to
> >> F()(a1,...,aN);
> >>
> >> If F is a function pointer type, this will clearly crash.
> >> A "regular"ized Boost.Lambda functor also will crash because of uninitialized error.
> >> After all, we need a lambda functor such that default-constructed one is callable.
> >
> > I think that we would need a way to inspect a lambda expression
> > template and see if it is stateless (i.e. it is not closing over
> > anything stateful). If it is stateful, static_ might abort compilation
> > if initialized with 'stateless':
> >
> > static_<always<F> >::type f = stateless; // does not compile if F is
> > not stateless.
>
> It is not a problem whether or not it is stateless.
> The problem is whether or not Default-constructed one is callable without crash.

In theory a stateless function object should always be callable without a crash.
Again, I always make my function objects stateless aggregates so I
have never incurred in such problems, but I understand that you want
Egg to be as general as possible.

> A default-constructed, regularized Boost.Lambda functor always crashes.
>

Well, a regularized boost.lambda is not stateless (it has at least a
boolean 'initialized' flag).

>
> > Anyways, I see that you take great care to guarantee static
> > initialization of stateful function objects. Do you really think this
> > is a case that is worth supporting? What are the use cases?
>
> A simple case is adapting a function-pointer.
>

Hum, if you want to have guaranteed static initialization, you need to
statically know the function pointer value:

template<typename Sig, Sig * p>
static_function_ptr {
   typedef typename result_of_sig<Sig>::type result_type;

   template<typename Args...>
   result_type operator()(Args.... args) {
       return p(args);
   }
};

Substitute the pseudo-variadic syntax with proper preprocessor magic :).

>
> > (for example, did you use this functionality when implementing oven?).
>
> Oven functions in namespace scope are neither stateful nor pointers,
> so that every function might be implemented using `static_`
> without complicated macros.
>

I thought so.

>
> > It seems to me that it complicates a lot the interface of the library
> > (with tons of ugly macros). I understand that this functionality is
> > opt-in (i.e. it is there only if you want it), but I feel
> > unconfortable. May be I'm worring too much, but I think that it really
> > makes the docs hard to follow.
>
> I'm really afraid that those macros may keep users away from the library.
>

Hey, maybe it is just me, maybe others won't have any problems with
them. I just find the macro based initialization ugly and unnecessary
complex.

IMHO what you could do is just omit it from the basic documentation
and reference and add an advanced section "static initialization of
stateful objects" where you show
how every function object adaptor in egg has a corresponding macro
that can be used to guarantee static initialization (with real-life
examples/use cases), at least an user does not have to know it until
it really needs it.

BTW, the documentation is my major problem with egg currently (I think
that it needs a much bigger walk though before going into 'reference
mode'), everything else are just details.

-- 
gpd

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