Closures

For the Compleat Fan
Locked
cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Closures

Post by cormullion »

What's the difference between newLISP closures and Lisp/Scheme closures? I've been reading http://lispy.wordpress.com/2007/10/25/w ... -hurt-you/:
So a closure turns out to be just a procedure with state.
The 'classic example' of the accumulator built-in to a function that he mentions has appeared on this forum too:

Code: Select all

(context 'gen) 

(define (foo) 
    (if (number? acc) 
        (inc 'acc) 
        (set 'acc 0))) 

(context MAIN) 

> (gen:foo) 
0
> (gen:foo) 
1 
> (gen:foo) 
2 
> (gen:foo) 
3 
Although this looks like a procedure with state, I know that Lutz has said that newLISP 'context closures' aren't closures...

So, what's the difference between newLISP 'closures' and Lisp/Scheme closures?

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

Closures are a feature of lexical scoping and dynamic function definition. For example, if you create a lambda inside another function, variables that are in the outer scope must be preserved for that lambda. When that lambda is later called, those variables that would have been available inside of the scope it was defined in are then activated in the current call's scope.

newLisp is dynamically scoped. Any time a function is called, it is called within the current scope, not the scope it was defined in.

newLisp has contexts, however, which are lexical namespaces that can simulate closures. You can do that with a functor (a function with the same name as its context, like foo:foo). The context preserves the symbols in the functor's scope, and they are available when the function is called later, no matter where it is called from.

However, the big difference is that within a context, dynamic scoping rules still apply. It is not a lexical scope. It is a lexically defined namespace that is parallel to the MAIN, dynamic scope. So:

Code: Select all

(setq foo:x "Hello world")
(define (foo:foo) (lambda () (println x)))
(setq x "Hello Corm")
(setq my-foo (foo:foo))
(my-foo) ; => prints "Hello Corm"
In Scheme, it would work like this:

Code: Select all

(define foo
  (lambda ()
    (let ((x "Hello world"))
      (lambda () (print x)))))

(define my-foo (foo))
(define x "Hello Corm")
(my-foo) ; => prints "Hello world"
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Right - so the article's description of closure being just 'a procedure with state' is not the whole story...

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

Well, it is a procedure with state, but that doesn't explain how that state is kept.
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

Locked