From: Andrew Le Couteur Bisson
Subject: How is function quoting implemented?
Date: 
Message-ID: <8d3uk9.a1q.ln@192.168.1.28>
I have written a Lisp interpreter which uses shallow binding and
therefore suffers from the funarg problem.  I would like to add
function quoting but I can't see any simple, efficient solution.
I use stack frames and create a frame for a function before its
arguments are evaluated.  The arguments are then evaluated into
the frame.  Binding the arguments is then a matter of swapping
the formal arguments previously bound values with the
evaluated arguments on the stack.  I can then swap back after
the function returns to restore the original environment.
As I see it, a quoted function should reference the stored
environment on the stack rather than the currently bound values
in the heap.  Is this correct?  Is there a better way to achieve
this?  All of the methods that I have explored so far have
degenerated into a monumental hack.  I am beginning to wonder
if the method that I have used to save and restore environments
is fundamentally flawed in this respect.
Any suggestions and/or references would be most welcome.

TIA
Andy

--
///////////////////////////////////////////////////////////////////
// Andrew Le Couteur Bisson //  ·····@syn-apps-sys.co.uk
// Software Engineer        //  ·············@virgin.net (personal)
// Syn-Apps-Sys             //  www.syn-apps-sys.co.uk
///////////////////////////////////////////////////////////////////
From: Pekka P. Pirinen
Subject: Re: How is function quoting implemented?
Date: 
Message-ID: <ulmkru50w.fsf@globalgraphics.com>
"Andrew Le Couteur Bisson" <···········@like.to.know> writes:
> I have written a Lisp interpreter which uses shallow binding and
> therefore suffers from the funarg problem.  I would like to add
> function quoting but I can't see any simple, efficient solution.

I'm not familiar with the term "function quoting", usually the
solution to the funarg problem is known as closing functions or making
lexical closures, which is indeed associated with #'.

> I use stack frames and create a frame for a function before its
> arguments are evaluated.  The arguments are then evaluated into
> the frame.  Binding the arguments is then a matter of swapping
> the formal arguments previously bound values with the
> evaluated arguments on the stack.  I can then swap back after
> the function returns to restore the original environment.

Sounds like you're holding the values of local variables in the
symbols that name them.  This is typical of Lisp interpreters, but not
the only way.

> As I see it, a quoted function should reference the stored
> environment on the stack rather than the currently bound values
> in the heap.  Is this correct?

That doesn't seem useful, unless there's some special stored
environment that you built to hold the variables that were closed
over.  In which case, it isn't really related to argument passing
anymore.  And what about LET-bound variables that you have closed
over?

Note that the enclosing functions of the closure have to refer to the
same environment as well, when they use these variables.  E.g.
  (let ((x 1))
    (funcall #'(lambda () (setf x 2)))
    (print x))

Storing the closure data on the stack has the problem that you can
only do downward closures, since the stack frame will only persist
until the function returns.  I.e.
  (mapcar #'(lambda (x) (+ x a)) foo)
is OK, but
  (defun adder (a) #'(lambda (x) (+ x a)))
wouldn't work.

Nevertheless, this type of solution is often used on Pascal-type
languages that only have downward closures and keep their local
variables on stack anyway.

A better way in Lisp is to heap-allocate an environment block to hold
the values (or even a separate "external value cell" for each
variable).  This is created and a pointer to it is installed in the
symbol's value cell when the variable is bound.  The interpreter needs
to recognize this case and perform an extra dereference.  The closure
is a record that holds the function and the environment block and
needs a special calling sequence to bind the closed-over variables to
the current values in the environment.
-- 
Pekka P. Pirinen
This article printed on 100% recycled electrons.