Update:
Don sets me straight, and rightfully so with a good exposition. I did not do my homework.
End Update
Don Box writes about compiling code on the fly in C# 3.0, kind of, I think...
Expression<Func<int, int>> expr = a => a + 3;
Console.WriteLine(expr); // prints "a => Add(a, 3)"
Func<int, int> func = expr.Compile(); // LCG's an MSIL method from the expr
Console.WriteLine(func(4)); // prints "7"
He equates (incorrectly from what I can tell) the above C# 3.0 with the following Scheme from 25 years ago...
(define expr '(lambda (a) (+ a 3)))
(display expr)
(define func (eval expr (scheme-report-environment 5)))
(display (func 4))
I think the comparison has some flaws. Maybe I just don't know enough about C# 3.0 (until just now I knew nothing about it).
First of all the expression (quote (lambda (a) (+ a 3))) is *data*, in particular a list of atoms and nested lists of atoms. That list is bound to a variable called expr
, whose name is conveying that the data *may* be evaluated as a lambda expression. But it is not a lambda expression, it is a list. The C# code appears to require something to be declared as an Expression
. Is such a class something that can be built programmatically? Or does it have to be declared and constructed intact?
Plus if it is already an expression, why would it need to be compiled? In the Scheme example, the list has to be evaluated to get a lambda, i.e. the function that the original list of atoms resembles. If you start with an expression, you should not have to do an eval or compile to get an evaluatable thing. That's just wrong. You'd just do this...
(define func (lambda (a) (+ a 3))) ; No QUOTE form. It's already a function.
(display (func 4)) ; Just apply it.
Or even more simply...
(display ((lambda (a) (+ a 3)) 4)) ; No QUOTE form. Just apply it.
One more thing: where is the QUOTE form in the C# code? The quote mark in Scheme is short hand for wrapping a special form (QUOTE ...)
around something that you consider "data". i.e. QUOTE prevents evaluation. Does the Expression
class automatically get recognized by the C# evaluator to prevent the RHS from being evaluated? Come on, either the RHS is data or the RHS is an expression. Or can the compiler only work with a special kind of data that happens to be called an Expression
. Weird any way you slice it from what I can make of it.
I don't get it, and maybe there is a more complete and logical explanation. Maybe the answer is "Pat, you're confused because you already know a simpler language like Scheme." Yeah, so why not use C++?
As it stands it looks like there is a bit of confusion and complication that separates C# 3.0 from simpler, more agile languages like Scheme, Python, and Ruby.
Just use those languages, folks. Don't get strung out on these incremental "improvements" to a language that was too complex to begin with.