[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: lexical mumblings

From: Miles Bader
Subject: Re: lexical mumblings
Date: 30 Oct 2001 23:52:18 +0900

Hi Andrew,

I read your notes, and have the following comments:

  1) For byte-codes, I think the implementation I suggested earlier is
     the right way to go, mostly because it's _so_ much simpler, and
     probably more efficient in the common case.

     As far as I can tell, the main potential advantage your approach
     has is that it defers creating heap environments for closed-over
     variables until the point where the closure is actually created at
     runtime, whereas my approach puts closed-over variables into an a
     heap-allocated environment-vector based only on compiler analysis
     (for cases where it's not obvious that the closure can't escape).

     However, my intuition is that this probably not much of an
     advantage in practice, and not worth the extra complexity.

  2) For the interpreter, your strategy seems reasonable.

     However, I'm making the assumption that it's not worth a lot of
     extra complexity to make the interpreter ultra efficient (that's
     what the byte-compiler is for), and that it's sufficient that it be
     `good enough' (after all, macros are expanded every time they're

     So I would make these suggestions:

       (a) Don't bother stack-allocating the interpreted environment
           blocks, just use normal lisp vectors (or alists, or

       (b) Just use a normal lisp (dynamically bound :-) variable to
           hold the current top of the interpreted environment stack.
           [call this `current-interp-lexenv' for reference]

     Then you basically get the following changes to existing lisp
     functions (here I'm assuming nil == no lexical environment, as
     distinct from an empty lexical environment):

        funcall just does:
                if (current-interp-lexenv != nil)
                   bind (current-interp-lexenv, nil)

        `llet' pushes stuff on current-interp-lexenv, by rebinding it

        `let' does:
                if (current-interp-lexenv != nil)
                   call `llet'
                   do normal let dynamic binding
           ;; this is to support the optional lexical binding

        `function' (the special form) of a lambda expr does:
                if (current-interp-lexenv != nil)
                   return (llambda current-interp-lexenv (args) body)
                   return (lambda (args) body)

        evaluating a `llambda' of course, just binds
        current-interp-lexenv to the enclosed environment.

    So, no GC magic, etc.

    The method I suggested earlier for turning on file-scope optional
    lexical binding could be implemented in the above framework by
    simply having `eval' bind current-interp-lexenv to an empty (not
    nil) environment block whenever `use-lexical-binding' was non-nil.

Yo mama's so fat when she gets on an elevator it HAS to go down.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]