Mark H Weaver <m...@netris.org> writes: > Andy Wingo <wi...@pobox.com> writes: >> On Wed 14 Dec 2011 00:00, Noah Lavine <noah.b.lav...@gmail.com> writes: >>> I haven't really been contributing to this thread, so please take my >>> opinion with a grain of salt. But it does appear to me that we should >>> support capturing a lexical environment, as Mark and David describe. >>> >>> So I took a look at ice-9/eval.scm.... >> >> The details of the interpreter's implementation are not public, I'm >> afraid. The interpreter does its job, but not quickly, and any change >> to make it better would involve a change to the environment >> representation. > > I agree that the returned "lexical environment object" should opaque. > Probably the only operation that needs this object is "local-eval", > though I'm not sure there's any disadvantage to printing it in > human-readable form for debugging purposes.
I was actually somewhat surprised that one could not just use "eval" here and give it the environment instead of a module argument. It is not actually obvious from the documentation whether the active module is part of the environment or not. To be fair, not much is obvious from the documentation of local-eval (documented in Guile 1.8, one occurence of "memoized" in this version). @c snarfed from debug.c:406 @deffn {Scheme Procedure} local-eval exp [env] @deffnx {C Function} scm_local_eval (exp, env) Evaluate @var{exp} in its environment. If @var{env} is supplied, it is the environment in which to evaluate @var{exp}. Otherwise, @var{exp} must be a memoized code object (in which case, its environment is implicit). @end deffn >> Anyway, it's looking in the wrong place. There is a compiler too. > > The most obvious implementation of (capture-lexical-environment) would > inhibit compilation of any top-level form that contains it. Well, it probably is less invasive than the equivalent of marking every local variable (similarly to global ones) as subject to change across calls. > Therefore, the only thing the compiler would need to do is detect the > presence of (capture-lexical-environment), and in that case, abort > compilation of the entire top-level form. I guess such a form should > be "compiled" simply as a call to the evaluator with the entire > top-level form as its argument. This would all happen after macro > expansion, of course. > > Does this make sense? Sounds a bit heavy-handed. For the use cases in Lilypond, I don't expect noticeable slow-downs as long as "the evaluator" works with reasonable performance for an interpreter and is not coded with the "we have a compiler anyway, so this will only run in exceptional cases and can be exceptionally slow" frame of mind. But it does a reasonably simple job, and probably is not significantly changed from Guile v1, so I don't expect much of a problem here. So this would basically work for Lilypond. It would, however, be likely a good idea to have it in a state where attaching strong-worded warnings to the documentation is not necessary. Something like "If an environment is being captured, the enclosing code can't be optimized (in the current implementation, it is simply left uncompiled). So it is a good idea to place performance-critical code in functions separate from those where you need to capture the environment." should likely be enough. -- David Kastrup