Code: Select all
(define-macro (qq)
(println (args)))
(define-macro (q)
(apply qq (args)))
Code: Select all
(q 3) => (3)
(q "abc") => ("abc")
(q x) => ('x)
(q 'x) => (''x)
(q ''x) => ('''x)
Thank you, Fanda
Code: Select all
(define-macro (qq)
(println (args)))
(define-macro (q)
(apply qq (args)))
Code: Select all
(q 3) => (3)
(q "abc") => ("abc")
(q x) => ('x)
(q 'x) => (''x)
(q ''x) => ('''x)
Code: Select all
(apply qq '(a b c)) => ('a 'b 'c)
(apply qq '(1 2 3)) => (1 2 3)
(apply qq '("a" "b" "c")) => ("a" "b" "c")
Code: Select all
> (map qq '(a b c))
('a)
('b)
('c)
(('a) ('b) ('c))
Code: Select all
(define-macro (qq) (args))
> (qq a b c)
(a b c)
> (apply qq '(a b c))
('a 'b 'c)
Code: Select all
(define (qq) (args))
> (qq a b c)
(1 2 3)
> (apply qq '(a b c))
(a b c)
Code: Select all
> (set 'a 1 'b 2 'c 3)
> (+ a b c)
6
> (apply + '(a b c))
value expected in function + : 'a
> (apply + '(1 2 3))
6
> (map + '(1 2 3) '(10 20 30))
(11 22 33)
Code: Select all
(define-macro (my+) (apply + (map eval (args))))
> (my+ a b c)
6
> (apply my+ '(a b c))
value expected in function + : 'a
> (apply my+ '(1 2 3))
6
> (map my+ '(1 2 3) '(10 20 30))
(11 22 33)
Now, I've always taken this to mean that the only difference between lambda and lambda-macro is that the former takes on evaluated arguments and the latter takes on unevaluated arguments. Is this right?Macros in newLISP are similar to define functions, but they do not evaluate their arguments. New functions can be created to behave like built-in functions that delay the evaluation of certain arguments. Since macros can access the arguments inside a parameter list, they can be used to create flow-control functions like those already built into newLISP.
Code: Select all
(set 'lst '(1 2 3))
(let (a 3)
(mydolist '(e lst)
'(+ a 3)))
Code: Select all
(let (a 3)
(eval (mydolist '(e lst) '(+ a 3))))
Code: Select all
(define-macro (my-or)
(let (val (eval (args 0)))
(if val val (apply my-or (rest (map eval (args)))))))
(my-or nil (cons 2 3)) => (2 3)
Code: Select all
(define (my-or)
(if (args 0) (args 0) (apply my-or (rest (args)))))
(my-or nil (cons 2 3)) => (2 3)
Code: Select all
(define (my-or p)
(if p p (apply my-or (args))))
(my-or nil (cons 2 3)) => (2 3)
Code: Select all
(define (my-or p)
(if p p (if (args) (apply my-or (args)) p)))
Right! That's why a 'mydolist' CL macro shouldn't call 'eval' in its definition (and one reason why CL and Scheme PL experts discourage its general use in this way), for it would break the semantic model I described in my last post. Now, because CL macros behave the way you describe, we can write "variable quantifiers" (which bind variables in the scope of their expressions (not their definitions)) in lexically scoped languages. This is how 'dolist' can respect the outer binding of 'a' by the 'let' in CL. This boils down to the fact that, even in lexically scoped languages, the bound variables are taken care of and we have to worry about how the free variables get their values (cf. my previous post).nikus80 wrote:suppose newLisp had lexical scoping. Forget macros for a second.
imagine there is a function mydolist that receives a quoted code, and very much behaves like dolist
when mydolist calls eval on '(+ a 3), what is the value of a? 3, you say. But only with dynamic scope. with lexical scope, if mydolist calls eval, it's evaled in the lexicals scope where mydolist was defined, which could be very different from the actual and where a could be undefined. So, with lexical scope, you have to receive a list and eval it in the current scope. Something likeCode: Select all
(set 'lst '(1 2 3)) (let (a 3) (mydolist '(e lst) '(+ a 3)))
which, by the way, is exactly how common lisp macros work.Code: Select all
(let (a 3) (eval (mydolist '(e lst) '(+ a 3))))
Ah yes, our original topic. (Sorry, Fanda.) What do you think about this?nikus80 wrote:about appling macros, ... I think [this] is not the desired behavior.
Code: Select all
(define-macro (my-or)
(let ((v (eval (args 0))))
(cond ((= (length (args)) 1) v) ; base case
((empty? (args)) nil) ; degenerate case
(true
(if v
v
(apply-macro my-or (rest (args))))))))
(define (apply-macro macro arglist)
(letex (macapp (cons macro (map quote arglist)))
(eval macapp)))
Code: Select all
> (apply-macro qq '(a b c))
('a 'b 'c)
invalid function : ('a 'b 'c)
called from user defined function apply-macro
Code: Select all
> (apply qq '(a b c))
('a 'b 'c)
('a 'b 'c)
Code: Select all
;; Here's a macro with a nested macro call of its argument.
(define-macro (myq)
(letex (arg1 (args 0))
(qq arg1)))
> (myq 'x)
('x)
('x)
;; Ah, this worked! But recall 'q' which uses 'apply':
> (q 'x)
(''x)
(''x)
Code: Select all
(set 'a 1 'b 2 'c 3)
(+ a b c) => 6
(apply + '(a b c)) => value expected in function + : 'a
Code: Select all
(set 'a nil 'x 9)
(my-or nil (cons 2 3)) => (2 3)
(my-or a (cons 2 3)) => (2 3)
(my-or x (cons 2 3)) => 9
(apply-macro my-or '(nil (cons 3 4))) => (3 4)
(apply-macro my-or '(a (cons 2 3))) => nil ; the evaluated a (*)
(apply-macro my-or '(x (cons 2 3))) => 9
Code: Select all
(eval (apply my-or '(nil (cons 3 4)))) => (2 3)
(eval (apply my-or '(a (cons 2 3)))) => nil
(eval (apply my-or '(x (cons 2 3)))) => 9
Code: Select all
(apply-macro macro argslist)
; the same as
(eval (apply macro argslist))
Code: Select all
(define-macro (my-or)
(if (empty? (args))
nil
(if (or (eval (args 0)) (= 1 (length (args))))
(eval (args 0))
(eval (cons 'my-or (rest (args)))))))
Code: Select all
> (my-or nil (ret-nil) (cons 2 3) (prit))
(2 3)
Code: Select all
(define-macro (my-or)
(let (val (eval (args 0)))
(if val val (apply my-or (rest (map eval (args)))))))
; and this better one if all members in the list are nil)
(define (my-or p)
(if p p (if (args) (apply my-or (args)) p)))
Code: Select all
(set 'x 9 'a nil)
> (eval (apply my-or '(nil (cons 3 4))))
(3 4)
> (eval (apply my-or '(a (cons 3 4))))
nil
> (eval (apply my-or '(x (cons 3 4))))
9
>
Code: Select all
(define (prit)
(print "printed!"))
(define (ret-nil)
'())
(define-macro (my-or)
(let (val (eval (args 0)))
(if val val (apply my-or (rest (map eval (args)))))))
(define (my-or2 p)
(if p p (if (args) (apply my-or2 (args)) p)))
(define-macro (my-or3)
(if (empty? (args))
nil
(if (or (eval (args 0)) (= 1 (length (args))))
(eval (args 0))
(eval (cons 'my-or3 (rest (args)))))))
(define (fun-my-or2 )
(let (val (eval (args 0)))
(if val
val
(apply fun-my-or2 (rest (args))))))
(define-macro (my-or4 )
(apply fun-my-or2 (args)))
> (my-or nil (ret-nil) (cons 2 3) (prit))
printed!(2 3)
> (my-or2 nil (ret-nil) (cons 2 3) (prit))
printed!(2 3)
> (my-or3 nil (ret-nil) (cons 2 3) (prit))
(2 3)
> (my-or4 nil (ret-nil) (cons 2 3) (prit))
(2 3)
>
Code: Select all
> (my-or3 nil (prit) (cons 2 3) (ret-nil))
printed!printed!"printed!"
>
Code: Select all
(define (prit) (print "printed!"))
(define (ret-nil) '())
(define-macro (my-or)
(let (v (eval (args 0)))
(if v v (if (args) (eval (cons 'my-or (rest (args))))))))
> (my-or nil (prit) (cons 2 3) (ret-nil))
printed!"printed!"
> (my-or nil (ret-nil) (cons 2 3) (prit))
(2 3)