I having been playing with a stack based language interpreter and
would like to set up lexical rather than dynamic scope in
closures. In each closure references to global variables are set
at the time that the closure is created.
I have implemented variable lookup using a global hash -- giving
dynamic scope. It struck me that if I could copy this global hash
and give each closure at the point of creation it's own hash that
I would have the scoping I require.
Having rounded up the usual suspects to no avail, and little
experience of copying hashes, is this a sane way to proceed? and
if so, how can I quickly copy a hash?
:)will
On Tue, 10 Apr 2001, Will Deakin wrote:
> I having been playing with a stack based language interpreter and
> would like to set up lexical rather than dynamic scope in
> closures. In each closure references to global variables are set
> at the time that the closure is created.
>
> I have implemented variable lookup using a global hash -- giving
> dynamic scope. It struck me that if I could copy this global hash
> and give each closure at the point of creation it's own hash that
> I would have the scoping I require.
>
> Having rounded up the usual suspects to no avail, and little
> experience of copying hashes, is this a sane way to proceed? and
> if so, how can I quickly copy a hash?
Dunno if this is sane or not, and "copy" is always a loaded word in this
newsgroup, but this should do what you want:
(defun copy-hash (hash)
(let ((new-hash (make-hash-table :test (hash-table-test hash)
:size (hash-table-size hash))))
(loop for key being the hash-keys of hash using (hash-value val)
do (setf (gethash key new-hash) val))
new-hash))
A-lists might be faster for typical programs in your language. Also,
"closure" usually implies some sharing between environments, which you
won't get just by copying scopes. But I'm sure there's a lot you're not
telling us :)
Tim
* Will Deakin wrote:
> I have implemented variable lookup using a global hash -- giving
> dynamic scope. It struck me that if I could copy this global hash and
> give each closure at the point of creation it's own hash that I would
> have the scoping I require.
What I did when doing something that is (I think) somewhat similar, is
to have an environment object which is either a wrapper around a
hashtable or a wrapper around an alist. You can could ask the
environment object to make a child object which was either of the same
class or could be a different class. Then the global environment was
a hashy one, but it was set up so its children were alisty ones -
working on the assumption that the global environment would have a lot
of entries but functions would typically bind only a very small number
of variables.
This was for a language with lispy semantics, so you need these
parent/child environments - you may not want that of course.
--tim