2014-12-01 67 views
3

Lisp noob here。在defun使用cond的Lisp评估

CL-USER> (defun my-if (a b c) 
      (cond (a b) 
       (t c))) 

CL-USER> (my-if t (print 1) (print 2)) 
1 
2 
1 

如果第一个是真的没想到拿到2,因为在cond第二条款不应该得到评估:

CL-USER> (cond (t (print 1)) 
       (t (print 2))) 
1 
1 

这是为什么我们需要宏,或我是否犯了一些其他错误?

回答

9

Common Lisp中的函数参数在进入函数之前进行评估。当(print 1)被评估时,它打印1并返回1。当(print 2)被评估时,它打印2并返回212进入功能。并返回1作为答案。

做你想做的事,你需要写一个宏:

CL-USER> (defmacro my-if (a b c) 
      `(cond (,a ,b) 
        (t ,c))) 
MY-IF 
CL-USER> (my-if t (print 1) (print 2)) 

1 
1 
+0

请注意,这与其他可能熟悉的语言的行为没有任何区别。例如,在类C或类似Java的语言中,定义如下:void my_if(boolean x,type then,type else){if(x){return then; } else {return else; }},在调用my_if(true,print(1),print(2));'你会看到1和2都打印出来。 – 2014-12-02 02:59:05

7

由于参数都得到评估,则需要延迟/力评价功能:

CL-USER 35 > (defun my-if (condition then-thunk else-thunk) 
       (cond (condition (funcall then-thunk)) 
        (t   (funcall else-thunk)))) 
MY-IF 

CL-USER 36 > (my-if t 
        (lambda() (print 1)) 
        (lambda() (print 2))) 

1 
1 

CL-USER 37 > (my-if nil 
        (lambda() (print 1)) 
        (lambda() (print 2))) 

2 
2 
+1

谢谢Rainer。宏是我所追求的,但这也是有趣和有启发性的 – 2014-12-01 16:57:08