我試了一下球拍這樣(和1 2 3)在R5RS中工作時爲什麼(申請和'(1 2 3))不起作用?
> (apply and '(1 2 3))
. and: bad syntax in: and
> (and 1 2 3)
3
有沒有人有這個想法?
我試了一下球拍這樣(和1 2 3)在R5RS中工作時爲什麼(申請和'(1 2 3))不起作用?
> (apply and '(1 2 3))
. and: bad syntax in: and
> (and 1 2 3)
3
有沒有人有這個想法?
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)))))
和my-and
可以與apply
使用。
爲了便於比較,這裏就是宏(這確實做短路)看起來像:
(define-syntax and
(syntax-rules()
((and) #t)
((and test) test)
((and test rest ...) (if test
(and rest ...)
#f))))
克里斯小丑,年輕的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
具有很好的屬性,您可以將它作爲函數傳遞,因爲它是一個函數。
目前仍然似乎少了一種選擇:一個and-function-delaying-evaluation
返回回當且僅當a
,b
,並c
所有返回true,但不評估,例如,b
和c
如果a
產生錯誤的。實際上,這可以通過功能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
類似的功能,你可以傳遞並仍然得到延遲評估;你只需要通過在函數中包裝東西來延遲評估,並讓類似的函數調用這些函數來產生值。 (在Scheme中,這可能是一個使用promise的機會。)
@ ChrisJester-Young感謝您的編輯!我知道我提到了翻譯,但我從來沒有做過翻譯。現在帖子更符合現在的問題。謝謝! –
因爲'and'是宏而不是函數。 –