From: Bill Birch
Subject: Adding FUNCTION to a shallow-binding interp.
Date: 
Message-ID: <1992Nov2.182028.22168@uk03.bull.co.uk>
Adding closures to a shallow-binding interpreter.

I have a shallow-binding interpreter, which has no lexical closure. 
My attempts to implement (function ) have been only partially succesful,
am I right in assuming that this is impossible?

So far my best attempt has been the following:

(defmacro my-function (fn)
`'(lambda (&rest f-args)
	((lambdaq ,(bound-oblist)
		(apply fn f-args))
	,@(mapcar 'eval (bound-oblist)))))

I should explain that in in the interpreter:

	lambdaq forms do not evaluate their arguments, 

	(bound-oblist) is a function that returns a list of all the symbols
	with bound values.

	symbols have only one value which can be a function 

; Simple test case:
(setq free 67)
(setq my-test (my-function (lambda (a) (cons a free))))
(print (my-test 12))
(setq free 88)
(print (my-test 12))

; produces:

; (12 . 67)
; (12 . 67)

The simple cases work ok, however  the following :

(setq free 67)
(setq my-test2 (my-function (lambda () (print free)(setq free 4))))
(my-test2)
(my-test2)

produces:
; 67
; 67

Where CLtL2 would want it to produce 67 4.

It is obvious why it cannot, but is there any way to do it?


Thanks in advance,

Bill

--
 Bill Birch             	|	·······@uk03.bull.co.uk
 Bull Info. Sys. Ltd.   	|       Bull Tel: 773 4367
 Maxted Road,         		|	Bull Mail: HM14 UK03 
 Hemel Hempstead,        	|	Tel: +44 442 884367
 HERTS, HP2 7DZ, U.K.         	|	Fax: +44 442 884570
                Aviate, Navigate, Communicate...
From: ·······@cc.helsinki.fi
Subject: Re: Adding FUNCTION to a shallow-binding interp.
Date: 
Message-ID: <1992Nov12.144242.1@cc.helsinki.fi>
In article <·····················@uk03.bull.co.uk>, ······@hemel.bull.co.uk (Bill Birch) writes:
> I have a shallow-binding interpreter, which has no lexical closure. 
> My attempts to implement (function ) have been only partially succesful,
> am I right in assuming that this is impossible?
You're right: it is impossible with the tools you're using.  Basically,
since the same name should have different bindings in each different
scope, you need a distinct storage location for each, and SETQ of a
local variable has to know about them.  A good test case is:

(defun two-functions(&aux x)
  (list #'(lambda () x) #'(lambda (y) (setq x y))))

Each call of TWO-FUNCTIONS has to create a new binding of X, which the
two functions share.

The standard solution for shallow-binding systems is external value
cells: a closed-over variable has a pointer to an external value cell,
which is a dynamically allocated object that holds the value of the
variable in that scope; each closure has a list of variables it closes
over and their external value cells.  For example, TWO-FUNCTIONS might
return something like this:

(#<closure (lambda () x) ((x . #1=#<external-value-cell nil))>
 #<closure (lambda (y) (setq x y)) ((x . #1#))>)

with new closures containing a new external value cell for each
invocation.  There are quite a few pitfalls in getting closures just
right, good luck!
___
Pekka P. Pirinen           ·············@helsinki.fi
Lisp implementor