Composing Fexprs Preserves Short-circuit Evaluation.
; One of the well known advantages of special operators over
; functions is that special operators apply "short-cuirciting".
;
; For example, operator "and" that evaluates
;
; (and (= 1 1) (= 2 2) (= 3 4) (= 5 (slow-function 6)))
;
; will never evaluate clause (= 5 (slow-function 6)). Instead,
; after (= 3 4) is recognized to be false, there is no theoretical
; possibility that whole expression evaluates to true, and
; nil is returned without evaluating other clauses.
;
; This is significant difference between operators and functions.
; If "and" was defined as function, all clauses would be evaluated
; first, and then passed to the operator "and."
;
; Only today I came to idea to test whether operator compose I
; defined few days ago, which can be applied on fexprs as well as
; on functions, preserves short-circuiting.
;
; I'll test it by defining two well known logical operators,
; nor and nand.
(set 'nor (compose not or))
(set 'nand (compose not and))
; Let us test whether 'nor' and 'nand' preserve short-circuit
; evaluation.
(nand (println "this should be done ")
(println "and this should be done")
(println (setf j nil))
(println "but this shouldn't be done"))
; this should be done
; and this should be done
; nil
;
(println "---")
(nor (println (= 1 2))
(println (= 1 3))
(println "and something different")
(println "this shouldn't be done"))
; ---
; nil
; nil
; and something different
; Everything works. Beautiful, isn't it?
(exit)
Bad weather in Croatia.
Composition of Functions or Macros.
; The composition of the functions is one of the basic mathematical
; operations. In this post, I'll try to define composition of
; functions and macros (Newlisp macros=fexprs) in Newlisp.
;
; Such composition should satisfy the following:
;
; ((composition 'f1 ... 'fn) _ _ _) = (f1 (f2 ... (fn _ _ _)))
;
; for all functions and macros.
;
; It wasn't that easy as I thought. First, I limited myself on the
; case of the composition of two functions. After some experimentation
; I came to that:
(set 'compose2 (lambda(f g)
(expand (lambda-macro()(letex((L (cons 'g (args))))(f L)))
'f 'g)))
; I tested it on simple example:
(println (compose2 'sin 'cos))
; (lambda-macro ()
; (letex ((L (cons 'cos (args)))) (sin L)))
(println ((compose2 'sin 'cos) 3) (sin (cos 3))) ; OK, it works.
; Then I tested it on two special, well, entities, i.e. identity
; function and identity macro:
(set 'I (lambda(x)x))
(set 'IM (lambda-macro(x)x))
(println ((compose2 'I 'sin) 3)) ; 0.1411200081, as it should be, i.e. (I (sin 3))
(println ((compose2 'sin 'I) 3)) ; 0.1411200081, as it should be, i.e. (sin (I 3))
(println ((compose2 'IM 'sin) 3)) ; (sin 3), as it should be, i.e. (IM (sin 3))
(println ((compose2 'sin 'IM) 3)) ; 0.1411200081, as it should be (sin (IM 3))
; OK; it appears it worked. Now I'll have to solve multi-version,
; I.e. composition of many functions or macros
(set 'compose (lambda()
(case (length (args))
(0 I) ; because (I (S x)) <=> (S x),
; no matter if S is function or macro
; so I can be always added from the left.
(1 (first (args)))
(2 (apply compose2 (args)))
(true (compose2 (first (args)) (apply compose (rest (args))))))))
(println ((compose sqrt) 65536)) ; 256
(println ((compose sqrt sqrt) 65536)) ; 16
(println ((compose sqrt sqrt sqrt) 65536)) ; 4
; OK, it works as well. However, result of the composing is
; rather complicated because of recursive definition
(println (compose 'f1 'f2 'f3 'f4))
; (lambda-macro ()
; (letex ((L (cons '(lambda-macro ()(letex ((L (cons '(lambda-macro ()(letex ((L (cons 'f4 (args))))
; (f3 L)))
; (args))))
; (f2 L)))
; (args))))
; (f1 L)))
;
;
; If iteration is used for definition of compose, then composition
; can be both shorter and faster - but not more elegant.
---
Alan Kay on Lisp and Fexprs.
89
Alan Kay on Lisp and Fexprs
Alan Kay is designer of Smalltalk. This citation is known, but not as well as it should be, and I think it deserves attention separately of many posts I wrote on fexprs. |
If you liked this article, you might be interested in On Pitman's 'Special forms in Lisp'. |
---
Subscribe to:
Posts (Atom)