Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Lambda abstractions in C++ vs. Scheme

Name: Anonymous 2009-07-03 12:54

In Scheme:
     (define foo (lambda (a b) (+ a b)))
The lambda-expression when evaluated produces the value of a procedural type. The define form binds this value to an identifier foo. Evaluation of an expression
     (foo 1 2)
looks up the procedural value bound to this identifier, and applies it.

In C++, precisely the same idea is expressed as

     Lambda((int a, int b), int, return a+b) foo;
where

     #define Lambda(args,ret_type,body) \
     class MakeName(__Lambda___) { \
     public: ret_type operator() args { body; } }
The Lambda construction creates a procedural type (class). The instantiation operator -- called 'declaration' in plain C -- "binds" this apply-able type to an instance foo. This sounds better in reverse: foo is bound to a value of a procedural type. Or, foo is instantiated as an object of a class that implements a callable interface.

When the compiler processes an application:
     cout << "foo(1,2) is " << foo(1,2) << endl;
it looks up the type of foo, finds the procedural class and invokes the appropriate method. The similarity between the two expressions -- in Scheme and C++ -- is almost complete. The major difference is a compile vs. run-time lookup of values and bindings. Optimizing Scheme compilers blur even this difference.

Name: Anonymous 2009-07-04 6:56

>>5
Recursive lambda-expressions

     (define fact (lambda (n) (if (not (positive? n)) 1
                                  (* n (fact (- n 1))))))

Note when the lambda expression itself is being evaluated -- to a procedural value -- an identifier fact it mentions is not bound to anything. The binding occurs afterwards, after the resulting procedural value is used by define. Yet this does not pose any problem: the lambda expression is not being applied yet at this point, it is merely "compiled". When the value of fact is indeed required, it will certainly have been bound.

In C++,

    Lambda((int n),int,
           if( n <= 0 ) return 1; else return n * (*this)(n-1))
    fact;

The above expression takes advantage of the fact that the "current object" can be referred by this within the body of a method. It explores the same kind of a 'lookup delay' as the Scheme expression above. When the body of a method is being compiled, there is no "current object" yet: this is only potentially bound. Later on, when the compiler sees an application of the method, it knows to which object the method is being applied to.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List