我正在阅读人工智能编程的范例: Peter Norvig 在Common LISP中的案例研究,在关于条件的特殊形式的章节中,它说它们都可以用if形式代替
(when test a b c) == (if test (progn a b c))
(unless test x y) == (if (not test) (progn x y)
(and a b c) == (if a (if b c))
(or a b c) == (if a a (if b b c))
(case a (b c) (t x)) == (if (eql a 'b) c x)
Run Code Online (Sandbox Code Playgroud)
我不明白它是如何工作的,有人能向我解释一下吗?那cond形式怎么样,它也可以用if形式代替吗?然后我就可以创建一个宏功能与if形式来替代when,unless,and,等...?
IF是一个通用条件,根据单个条件从两个分支中选择.所有这些都是别人写它的时候有两个以上的分支(只是更简单的方法AND,OR,CASE),或者只有一个分支(WHEN,UNLESS).
COND也可以用IF,例如:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defun ifify-clauses (clauses)
(when clauses
(destructuring-bind (condition form) (first clauses)
`(if ,condition ,form ,(ifify-clauses (rest clauses)))))))
(defmacro if-cond (&body clauses)
(ifify-clauses clauses))
(macroexpand '(if-cond
((= 3 1) "foo")
((= 3 2) "bar")
((= 3 3) "quux")))
;=> (IF (= 3 1)
; "foo"
; (IF (= 3 2)
; "bar"
; (IF (= 3 3)
; "quux"
; NIL)))
Run Code Online (Sandbox Code Playgroud)
这不仅是可能的,而且恰恰是您使用时发生的事情cond:
(macroexpand '(cond ((< v 0) (print "negative") (* -2 v))
((> v 0) (print "positive") (1- (* 2 v)))
(t (print "zero") 0)))
; ==>
(if (< v 0)
(progn (print "negative")
(* -2 v))
(if (> v 0)
(progn (print "positive")
(1- (* 2 v)))
(progn (print "zero")
0)))
Run Code Online (Sandbox Code Playgroud)
所以当你cond在CL中使用时,它会if在宏扩展阶段用等效的形式替换它.对于程序中使用宏的每个位置,通常会发生一次.
通常核心语言不支持很多方法来做同样的事情所以我想一切都将被转换为if除非实现找到保持原始的理由.
CLHS通过表格的标题将其反映为" 特别操作员IF "和" 宏观COND ".
您可以定义自己的宏来执行条件,并且您可以自由选择已经可用的条件来替换它,因为宏已经扩展,直到不再剩下.这是一个照应的定义,如果:
(defmacro aif (p a &optional c)
`(let ((it ,p))
(if it ,a ,c)))
(macroexpand '(aif (extremely-expensive-function x)
(use-value it)
(compute-other-result)))
; ==>
(let ((it (extremely-expensive-function x)))
(if it
(use-value it)
(compute-other-result)))
Run Code Online (Sandbox Code Playgroud)