There are really two very distinct answers to your question. First let me show how to rewrite your 'make-multiplier' example in newLISP in an interactive console session:
Code: Select all
> (define (make-multiplier x) (expand (fn (m) (* x m)) 'x))
(lambda (x) (expand (lambda (m) (* x m)) 'x))
> (define doubler (make-multiplier 2))
(lambda (m) (* 2 m))
> (doubler 13)
26
> (define tripler (make-multiplier 3))
(lambda (m) (* 3 m))
> (tripler 13)
39
>
The second answer:
There is now such thing as closures in newLISP, and I would not try simulating closures in newLISP. To code state-keeping functions newLISP uses contexts (namespaces).
Here is a quick crash course in to coding state full functions in newLISP:
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
This way to write state keeping functions is good for bigger code size and when there are several function in the same namespace.
When just writing a little snippet there is a shorter way without bracing it with context switches:
Code: Select all
(define (gen:foo)
(if (number? gen:acc)
(inc 'gen:acc)
(set 'gen:acc 0)))
> (gen:foo)
0
> (gen:foo)
1
> (gen:foo)
2
> (gen:foo)
3
A function inside a namespace with the same name as the namspace is called a
default function. Default functions can be called just using the name space name:
Code: Select all
(define (gen:gen)
(if (number? gen:acc)
(inc 'gen:acc)
(set 'gen:acc 0)))
> (gen)
0
> (gen)
1
> (gen)
2
> (save "gen.lsp" 'gen) ; now look at the file gen.lsp !
The last line shows how a function and its state can be easily serialized to a file.
newLISP is a 'new' function to duplicate/copy namespace objects and a 'def-new' to duplicate just portions for mixins. You should read the relevant chapters in the manual:
Chapter 16 (read this first):
file:///usr/share/newlisp/doc/newlisp_manual.html#context_objects
Chapter 15:
file:///usr/share/newlisp/doc/newlisp_manual.html#contexts
Lutz