Parallel "Expand"Almost all Lisp dialects support both "parallel" and "serial" assignment operators like let and letn in Newlisp. For example
(setf y 1)
(let((y 2)(x y)) x) ==> 1 (parallel)
but
(setf y 1)
(letn((y 2)(x y)) x) ==> 2 (serial)
Expand-expression in Newlisp
(expand '(x y) 'x 'y)
results in replacement of x and y in (x y) with values of x and y. Expand-expression in other form:
(expand '(x y) ((x <value1>)(y <value2>)))
results in replacement of x and y in (x y) with <value1> and <value2>. In both cases, the replacement is performed in serial fashion. For example,
(expand '(x y) '((x y)(y 3))) ==> (3 3)
In this post I present the implementation of parallel expand, expand// in Newlisp; two slashes in name remind on parallel lines such that, for instance
(expand// '(x y) '((x y)(y 3))) ==> (y 3).
Parallel expand expression can be reduced to serial expand with introduction of new variables.
(expand// <expr> '((<var1> <val1>)...(<varn> <valn>))) =
(expand <expr> '((<var1> expand//1) ... (<varn> expand//<n>)
(expand//1 <val1> ) ... (expand//n <valn>)))
Fexpr expand// can use always the same temporary variables expand//1, ..., expand//n, without need for generating fresh variables each time expand// is called. Other form of expand//,
(expand// <expr> '<var0> ... '<varn>)
can be reduced on form
(expand <expr>
'((<var0> expand//0) ... (<varn> expand//<n>)
(expand//0 <value of var0>) ... (expand//<n> <value of var<n>>))).
Using that idea, the implementation is not very technical (define (expand// expr) (letn((a (args)) (expand//sym (lambda(n)(sym (append "expand//" (string n))))) (expandlist (if (empty? a) (throw-error "expand//: arguments missing.") (cond ((symbol? (first a)) (append (map (lambda(i)(list i (expand//sym $idx))) a) (map (lambda(i)(list (expand//sym $idx) (eval i))) a))) ((list? (first a)) (append (map (lambda(i)(list (i 0) (expand//sym $idx))) (first a)) (map (lambda(i)(list (expand//sym $idx) (i 1))) (first a)))))))) (println "expandlist=" expandlist) (expand expr expandlist))) (setf x 'y) (setf y 3) (println (expand '(x y) 'x 'y)) ; => (3 3) (println (expand// '(x y) 'x 'y)) ; => (y 3) (println (expand '(x y) '((x y)(y 3)))) ; => (3 3) (println (expand// '(x y) '((x y)(y 3)))) ; => (y 3) (exit) |
--