首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么(apply and '(1 2 3))不工作,而(和1 2 3)在R5RS中工作?

为什么(apply and '(1 2 3))不工作,而(和1 2 3)在R5RS中工作?
EN

Stack Overflow用户
提问于 2013-06-21 17:49:06
回答 2查看 448关注 0票数 5

我在球拍上试过,就像这样

代码语言:javascript
复制
> (apply and '(1 2 3))
. and: bad syntax in: and
> (and 1 2 3)
3

有人对此有什么想法吗?

EN

回答 2

Stack Overflow用户

发布于 2013-06-21 20:06:18

Chris Jester-Young的answer是对的,但还有一点我想强调。标准的and运算符是一个宏,它通过(本质上,如果不是准确的话)将(and a b c)转换为(if a (if b c #f) #f)来延迟其参数的计算。这意味着如果a为false,则不会计算bc

我们还可以选择定义一个and-function,以便(and-function a b c)计算abc的值,并在这些值都为真时返回true。这意味着将对所有abc进行求值。and-function有一个很好的属性,你可以将它作为函数传递,因为它是一个函数。

似乎还缺少一个选项:当且仅当abc都返回true时,返回return的and-function-delaying-evaluation,但如果a返回false,则不计算bc。实际上,这可以通过函数and-funcalling-function来实现,该函数要求其参数是一组函数。例如:

代码语言:javascript
复制
(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语义的东西:

代码语言:javascript
复制
(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的机会。)

票数 11
EN

Stack Overflow用户

发布于 2013-06-21 18:32:53

and不是一个函数,它是一个宏,所以你不能像传递函数一样传递它。

and是宏的原因是为了实现短路行为。您可以制作自己的非短路版本:

代码语言:javascript
复制
(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

为了便于比较,下面是宏(执行短路操作)的样子:

代码语言:javascript
复制
(define-syntax and
  (syntax-rules ()
    ((and) #t)
    ((and test) test)
    ((and test rest ...) (if test
                             (and rest ...)
                             #f))))
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17232240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档