我在球拍上试过,就像这样
> (apply and '(1 2 3))
. and: bad syntax in: and
> (and 1 2 3)
3有人对此有什么想法吗?
发布于 2013-06-21 20:06:18
Chris Jester-Young的answer是对的,但还有一点我想强调。标准的and运算符是一个宏,它通过(本质上,如果不是准确的话)将(and a b c)转换为(if a (if b c #f) #f)来延迟其参数的计算。这意味着如果a为false,则不会计算b和c。
我们还可以选择定义一个and-function,以便(and-function a b c)计算a、b和c的值,并在这些值都为真时返回true。这意味着将对所有a、b和c进行求值。and-function有一个很好的属性,你可以将它作为函数传递,因为它是一个函数。
似乎还缺少一个选项:当且仅当a、b和c都返回true时,返回return的and-function-delaying-evaluation,但如果a返回false,则不计算b和c。实际上,这可以通过函数and-funcalling-function来实现,该函数要求其参数是一组函数。例如:
(define (and-funcalling-function functions)
(or (null? functions)
(and ((car functions))
(and-funcalling-function (cdr functions)))))
(and-funcalling-function
(list (lambda () (even? 2))
(lambda () (odd? 3))))
; => #t
(and-funcalling-function
(list (lambda () (odd? 2))
(lambda () (even? 3)))) ; (even? 3) does not get evaluated
; => #f使用宏和这个习惯用法,我们实际上可以实现一些具有标准and语义的东西:
(define-syntax standard-and
(syntax-rules ()
((standard-and form ...)
(and-funcalling-function (list (lambda () form) ...)))))
(macroexpand '(standard-and (odd? 2) (even? 3)))
; =>
; (and-funcalling-function
; (list (lambda () (odd? 2))
; (lambda () (even? 3))))当然,从中得到的教训是,您可以传递一个and-like函数,但仍然可以获得延迟计算;您只需通过将内容包装在函数中并让and-like函数调用这些函数来生成值来延迟计算即可。(在Scheme中,这可能是使用promises的机会。)
发布于 2013-06-21 18:32:53
and不是一个函数,它是一个宏,所以你不能像传递函数一样传递它。
and是宏的原因是为了实现短路行为。您可以制作自己的非短路版本:
(define (my-and . items)
(if (null? items) #t
(let loop ((test (car items))
(rest (cdr items)))
(cond ((null? rest) test)
(test (loop (car rest) (cdr rest)))
(else #f)))))并且可以与apply一起使用my-and。
为了便于比较,下面是宏(执行短路操作)的样子:
(define-syntax and
(syntax-rules ()
((and) #t)
((and test) test)
((and test rest ...) (if test
(and rest ...)
#f))))https://stackoverflow.com/questions/17232240
复制相似问题