and 的转换可以在报告中看到,但不包括实际的宏基本上是这样的:
; only one argument
(and a) ; ===>
a
; one of more
(and a b ...) ; ==>
(if a
(and b ...)
#f)
所有参数的计算结果必须为正值,最后一个值是结果,否则 #f。它会短路,所以当某些东西是 #f 时,其余的表达式永远不会被评估。
对于or 是这样的:
(or a) ; ==>
a
(or a b ...) ; ==>
(let ((a-value a))
(if a-value
a-value
(or b ...)))
返回第一个不等于 #f 的参数。如果所有值都是#f,则最后一个#f 将是结果。
如果你愿意的话:
(if a b c) ; ==>
(let ((tmpa a))
(or (and atmpa b)
(and (not atmpa) c)) ; not part only important if b can be #f
我使用let 来防止多次计算同一个表达式。例如。如果你有一个打印类似(begin (display "hello") #f) 的东西,或者这是一个昂贵的计算,那么它是必要的,否则你可以用表达式替换变量。例如。最后一个会变成:
(or (and a b)
(and (not a) c))
没有临时变量的变回变成:
(if (if a b #f)
(if a b #f)
(if (not a) c #f))
如果 b 是 #f 值,那么结果是 #f,因为最后一个 if。因此每次a 为真b 就是结果。每次都是假的,c 就是答案。因此
(if a b c)
假设你想返回列表中的第一个真值。
(define (first-true lst)
(and (not (null? lst))
(car lst)
(first-true (cdr lst))))