
On Mon, Feb 16, 2004 at 09:19:07PM +0900, Darren Cook wrote:
Hi, I've read the lambda sections of the FC++ docs, and the paper on the subject, and am a bit confused how to use it. Could you show the FC++ equivalents of these BLL examples:
Sure. I'm including just bits of commentary and code snippets in reply to each example, and then I have also attached a full program which demonstrates all this.
1. (from the paper) int a[]={5,3,8,4}; std::for_each(a,a+4,std::cout<<_1<<"\n");
In FC++ it'd look like this: std::for_each(a,a+4, lambda(X)[ &cout %out_stream% X %out_stream% '\n' ] ); "out_stream" is the FC++ named functoid which refers to the << operator. Unlike the real operator, it takes a stream _pointer_ as the left-hand argument (because FC++ uses value semantics, and thus references are icky). The %s are FC++'s lambda infix syntax; recall that for any FC++ functoid f, you can say f(x,y) or x ^f^ y to call f "now" with args x and y, or you can say f[x,y] or x %f% y to do the same thing inside lambda to delay evaluation and turn the call into a lambda expression.
2. int a[]={5,3,8,4}; std::for_each(a,a+4,std::cout<<constant("v=")<<_1<<"\n");
std::for_each(a,a+4, lambda(X)[ &cout %out_stream% string("v=") %out_stream% X %out_stream% '\n' ] ); Same thing here, with the added annoyance that you have to manually turn the string literal into some "by-value" type (rather than the "array of char const" type the darn templates deduce--ugh). The %s (rather than ^s) ensure that evaluation happens "later", serving the same purpose as boost::lambda's constant().
3. (a vector of MyClass pointers) std::for_each( tests.begin(), tests.end(), bind(&MyClass::save,_1,f) );
Here you would probably do std::for_each( tests.begin(), tests.end(), ptr_to_fun(&MyClass::save)(_,5) ); assuming that "save" is a normal method. ptr_to_fun() converts a C++ function pointer into an FC++ functoid (with an extra "this" parameter for member functions). Here we use the short for for partial application: f(_,5) which means the same as lambda(X)[ f[X,5] ] Note that if "save" were defined by MyClass as a functoid, things get even easier in the client code; see the attached example (and YourClass) for details.
4. std::for_each( tests.begin(), tests.end(), bind(delete_ptr(), _1) );
In FC++ we have a functoid called "delete_": std::for_each( tests.begin(), tests.end(), delete_ );
5. (in a spirit parser) Node= +( (+range_p('A','Z'))[bind(&MyClass::on_name, this, _1,_2)]
+( ch_p('[') (*(anychar_p-']'))[bind(&MyClass::on_value, this, _1,_2)] ch_p(']') ) );
I didn't do these examples (seemed to require too much extra context), but the gist of it would again be that bind(&MyClass::on_name, this, _1,_2) would be spelled ptr_to_fun(&MyClass::on_name)(this) // or, equivalently // ptr_to_fun(&MyClass::on_name)(this,_,_) in FC++ if "on_name" is a plain method, or MyClass::on_name(this) if it were a functoid. See the attached program for more detail if you like, and please ask more questions if you have them. Brian -- -Brian McNamara (lorgon@cc.gatech.edu)