I was at LispNYC last night listening to Anton van Straaten discuss his work on R6RS, the new Scheme standard. One surprising change from R5RS is that eval is defined in a library.
Eval, in a library? Holy scopes! The Common Lispers in the audience were aghast. Even the Schemers were a tad confused. Anton explained. The goal of Scheme, he said, has always been to incorporate as much dynamic behavior as possible without sacrificing efficient compilation. Towards this end, the R6RS eval is more limited than Common Lisp’s eval.
As I understand it, eval was central to McCarthy’s original design for LISP. Eval is LISP, and LISP is eval. Of course, as others reminded me later, LISP’s definition of eval with dynamic scope led to the 30-year “funarg” bug. Eval is also a thorn in the side of anyone trying to generate a standalone Common Lisp program — the possibility of a call to eval means the compiler has to include the entire Common Lisp runtime (up to 20 MB, depending on the implementation) in the final executable.
This got me thinking about Ruby, too. While Common Lisp and Scheme actually discourage the use of eval, Ruby is pretty casual about it. In a purely interpreted, dynamic language, that’s not a problem. But it would make it tough to implement a static Ruby compiler.
Came across this while googling. One point I’d like to add is that as “recently” as R4RS, eval wasn’t a standard part of Scheme. There’s an old FAQ on the subject, “Why is there no EVAL in Scheme?”, at: http://www.faqs.org/faqs/scheme-faq/part1/section-12.html . So the question of how or even whether to handle eval isn’t a new one for Scheme by any means.
The FAQ describes three positions regarding eval in the Scheme community at that time. By not specifying eval, R4RS effectively endorsed the first position, although of course implementations could go ahead and do their own thing. R5RS specified a strange hybrid between the second and third positions: it required an environment to be specified, but offered no facilities for manipulating environments, so ended up not guaranteeing much at all. R6RS adds better support for the third position, linking the issue of eval’s environment to the module system. This also still caters to the first position, by allowing static knowledge of the dependencies of eval.
I think surprise on this issue may have been fostered by non-standard extensions in some of the more dynamic implementations, or by exposure to other Lisps. But when viewed in the context of Scheme’s history on the subject, R6RS eval is very appropriate to a Scheme standard.