Related articles |
---|
How to implement lexical closures? grom358@gmail.com (grom) (2010-05-06) |
Re: How to implement lexical closures? sleepdev@gmail.com (andy johnson) (2010-05-09) |
Re: How to implement lexical closures? gneuner2@comcast.net (George Neuner) (2010-05-09) |
Re: How to implement lexical closures? cr88192@hotmail.com (BGB / cr88192) (2010-05-09) |
Re: How to implement lexical closures? torbenm@diku.dk (2010-05-10) |
Re: How to implement lexical closures? grom358@gmail.com (grom) (2010-05-11) |
Re: How to implement lexical closures? cr88192@hotmail.com (BGB / cr88192) (2010-05-12) |
Re: How to implement lexical closures? gene.ressler@gmail.com (Gene) (2010-05-12) |
Re: How to implement lexical closures? gah@ugcs.caltech.edu (glen herrmannsfeldt) (2010-05-13) |
[7 later articles] |
From: | George Neuner <gneuner2@comcast.net> |
Newsgroups: | comp.compilers |
Date: | Sun, 09 May 2010 19:31:16 -0400 |
Organization: | A noiseless patient Spider |
References: | 10-05-031 |
Keywords: | storage |
Posted-Date: | 10 May 2010 01:20:58 EDT |
On Thu, 6 May 2010 21:22:21 -0700 (PDT), grom <grom358@gmail.com>
wrote:
>I'm working on a toy interpreter (http://code.google.com/p/zemscript/)
>and trying to implement lexical closures (http://code.google.com/p/
>zemscript/source/browse/#svn/branches/lexical_scope) .
>
>However since it copies the symbol table the following does *not*
>work:
>create = function() {
> x = 0;
> return {
> "get" : function() { return x; },
> "set" : function(v) { x = v; }
> };
>};
>
>o = create();
>o["set"](42);
>println(o["get"]()); // Should print 42
>
>What I can't work out is how I can get the second example to work
>without breaking the first example.
>
>Ant build file: http://pastebin.com/qDaZethE
I don't know the semantics of you language and so the intent of the
code above is not exactly clear. In particular, I'm not sure whether
'o' represents a function or an object with methods.
Regardless, you need to create 2 separate closures - one for 'get' and
one for 'set', closing both over the same variable x.
In Scheme I'd approximate (what I believe to be) the functionality of
your code with something like:
(define create
(lambda ()
(let ((x 42))
(let ((funcs (list
(cons 'get (lambda () x))
(cons 'set (lambda (v) (set! x v)))
)))
(lambda (cmd . arg)
(let (if (assoc cmd funcs)))
(if f
(if (eq? arg '())
((cdr f))
((cdr f) (car arg)) )
(error "undefined function")
)))
))))
(define bar (create))
(define baz (create))
> (bar 'get)
42
> (baz 'get)
42
> (bar 'set "hi")
> (bar 'get)
"hi"
> (baz 'get)
42
> (baz 'set)
#<procedure>: expects 1 argument, given 0
> (baz 'quit)
undefined function
In case you can't decipher the Scheme, the function 'create' creates
an environment containing the variable 'x', creates a second
environment containing 2 anonymous functions closed over 'x' and an
association list pairing the symbols 'get and 'set to their respective
functions, and creates and returns an anonymous function in the root
environment, closed over the second environment in which it looks up
its first argument and applies the associated function passing its
second argument.
The [paraphrased] environment picture looks like:
+-------------------------------------------------------+
| #proc3: (cmd,arg) {if (cmd in funcs) funcs[cmd](arg)} |
| create: () { return #proc3 } |
| bar : #proc3 |
| baz : #proc3 |
+-------------------------------------------------------+
|
+------+ |
| x:42 | <--+ |
+------+ | |
| V
+---------------------------------------------+
| #proc1: () { return x } |
| #proc2: (v) { x = v } |
| funcs : list(('get, #proc1),('set, #proc2)) |
+---------------------------------------------+
What you need to do for your language depends on its semantics, but
generally you don't want to copy environments[*], but rather create
new ones as necessary, bind their variables, and chain them together
according to the lexical structure of the language. Closures then
link functions to the tree of environments that the functions require
to work.
[*] except maybe as a 1st step to evaluate untrusted code.
Hope this helps.
George
Return to the
comp.compilers page.
Search the
comp.compilers archives again.