* FLIM-ELS (flim-modules): Add `ew-var' and reorder.
[elisp/flim.git] / closure.el
1 (provide 'closure)
2
3 (defmacro closure-make (fun &rest fvs)
4   "Make closure from function FUN and free variable list FVS.
5 CAUTION: Do not assign to free variables."
6   (let* ((funv (make-symbol "funv"))
7          (args (make-symbol "args")))
8   `(list
9     ,fun
10     (lambda (,funv ,args ,@fvs)
11       (apply ,funv ,args))
12     ,@fvs)))
13
14 (defun closure-call (clo &rest args)
15   "Call closure."
16   (if (functionp clo)
17       (apply clo args)
18     (apply (cadr clo) (car clo) args (cddr clo))))
19
20 (defun closure-compose (c1 c2)
21   "Compose C1 and C2.
22
23 If either C1 or C2 is nil, another one is returned.
24 If C1 and C2 is non-nil, C1 must be closure with one argument."
25   (cond
26    ((null c1) c2)
27    ((null c2) c1)
28    (t
29     (closure-make
30      (lambda (&rest args)
31        (closure-call c1 (apply 'closure-call c2 args)))
32      c1 c2))))
33
34 '(
35
36 (setq c1 (let ((a 1)) (closure-make (lambda (b) (+ a b)) a)))
37 (closure-call c1 2) ; => 3
38
39 (let ((a 1)) (setq plus1 (closure-make (lambda (b) (+ a b)) a)))
40 (let ((a 2)) (setq plus2 (closure-make (lambda (b) (+ a b)) a)))
41 (setq plus3 (closure-compose plus1 plus2))
42 (closure-call plus3 4) ; => 7
43
44 )