;---------------------------------------------------------------
; INTRODUCTION
;
; In Lisp generally, including Newlisp, let is defined through
; lambda. According to Newlisp manual
;
; (let ((sym1 exp-init1) [ (sym2 exp-init2) ... ] ) body)
;
; is equivalent to
;
; ((lambda (sym1 [sym2 ... ])
; exp-body)
; exp-init1 [ exp-init2 ...])
;
; What happens if we use lambda-macro instead lambda on the same
; way?
;---------------------------------------------------------------
; I'll define
;
; (met ((sym1 exp-init1)
; ...
; (symn exp-initn))
; body)
;
; as a macro call that translates to the expression
;
; ((lambda-macro(sym1 ... symn)
; body)
; exp-init1
; ...
; exp.initn)
;
; end evaluates it.
(set 'met (lambda-macro()
(letn((initializations (first (args)))
(new-macro (append (lambda-macro)
(list (map 'first
initializations))
(rest (args))))
(equivalent-expression
(cons new-macro
(map (lambda(x)
(first (rest x)))
initializations))))
(eval equivalent-expression))))
; What such a met control structure does? Almost the same thing as
; let, just initialization will be done in "macro style", ie. if
; I write
;
; (met ((sym1 (+ 2 3))
; (sym2 (+ 3 4)))
; ...)
;
; the value of sym1 will not be RESULT of evaluation of (+ 2 3),
; but expressions (+ 2 3) itself, just like I wrote
;
; (let ((sym1 '(+ 2 3))
; (sym2 '(+ 3 4)))
; ...)
;
;Test:
(met ((sym1 (1 2 3))
(sym2 (4 5 6)))
(println (append sym1 sym2)) ; output: (1 2 3 4 5 6)
(println (list sym1 sym2))) ; output: ((1 2 3) (4 5 6))
; Yap, it works. But, what happens if I make tricky attack on
; my new account with something like?
(met ((sym1))
(println "sym1=" sym1))
; It works as well, output is sym1=nil, just like it would be with
; let. It is the consequence of the (first (rest x)) returning nil,
; if x has only one element, unlike (nth 1 x) that produces error.
; (Newlisp has the "local" expression that can be used for similar
; purposes. Check it - it is good thing.)
; Another tricky attack with "empty" met, as a edge case? Does it work?
(met ()
(println "Hello world"))
; It does - it doesn't generate an error, and that's all we need.
;---------------------------------------------------------------
; If "let" has a relative "letn", what about equivalent relative
; "metn" of "met"?
;
; (metn ((sym1 exp-init1)
; (sym2 exp-init2)
; ....
; (symn exp-initn))
; body)
;
; should be equivalent to
;
; (met ((sym1 exp-init1))
; (met ((sym2 exp-init2))
; ...
; body)...))
; However, there is no use of that, because in both metn and met,
; exp-init1, ... are NOT evaluated until body starts to be evaluated,
; hence met and metn should have exactly the same effect - except
; that met should be faster. Why - see my post "New copies discovered".
;---------------------------------------------------------------
; CONCLUSION:
;
; Is such a "met" useful? Theoretically, it is as useful as lambda-macro.
; It spares one apostroph and makes programs more readable. However,
; let-expressions are already complicated enough so extra apostroph
; is not nearly such a nuisance as it can be in some macro calls that
; look like control structures. Nevertheless - why not?
If lambda Gives let, What About lambda-macro?
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment