Boost logo

Boost :

Subject: Re: [boost] phoenix::bind
From: Joel de Guzman (joel_at_[hidden])
Date: 2008-10-02 18:53:42


Peter Dimov wrote:

> Now that I've seen what Phoenix can do, I think that, were I to design a
> Boost.Lambda2, I'd probably go with a classic lambda of the form
>
> lambda( _x, _y )[ _x + _y ]
>
> where the inner _x + _y is not a function object, and it is the lambda[]
> that turns it into one. (That is, the evaluation of an inner expression
> would be done with eval(expr, args...) and not with expr(args...).)

That is actally what's happening internally already.

> Local state would look like
>
> lambda( _x, _a = 0 )[ _a += _x ]
>
> and one can also extend this to lambda( byval, ... ) and lambda( byref,
> ... ) to control the default capture behavior.

Interesting.

I'd spell function
> application inside a lambda as apply( f, x ) and not as bind, leaving
> the latter as an alias for lambda[ apply ].

Hmm, right.

> So \f \x f (f x) would be
>
> lambda( _f )[ lambda( _x ) [ apply( _f, apply( _f, _x ) ) ] ]
>
> Using the above example as a test for this theory:
>
>> for_each(arg1,
>> lambda(_a = arg2)
>> [
>> push_back(arg1, _a)
>> ]
>> )
>
> In lambda terms, it's something like
>
> \x,y for_each( x, \z push_back( z, y ) )
>
> so (with lazy for_each and push_back):
>
> lambda( _x, _y )[ for_each( _x, lambda( _z )[ push_back( _z, _y ) ] ) ]
>
> This implies that a lambda[] must be able to access an outer scope. I
> wonder how could one do that. :-) The outer lambda should be able to do
> some term rewriting, I guess.

Phoenix already does that. See let visibility:
http://tinyurl.com/3qq2bl

It's one of the early requirements. I'm quite happy with it. Hah,
those were one of the sleepless coding nights. Example
from the doc:

     let(_x = 1, _y = ", World")
     [
         // _x here is an int: 1

         let(_x = "Hello") // hides the outer _x
         [
             cout << _x << _y // prints "Hello, World"
         ]
     ]

anything you can do with "let", you can do with "lambda".

> I should also be able to spell that as:
>
> lambda( _x, _y )[ for_each( _x, lambda( _x )[ push_back( _x, _y ) ] ) ]
>
> with the two _x being properly scoped.

Yep. Phoenix can do that. A local variable may hide an outer local
variable. Here, we just reuse the locals for arguments to the
lambda as well. So, in current terms, this:

     lambda( _x, _y )[ _x + _y ]

is just this:

     lambda( _x = _1, _y = _2 )[ _x + _y ]

Very cool suggestion, Peter!

Regards,

-- 
Joel de Guzman
http://www.boostpro.com
http://spirit.sf.net

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