为什么以下代码无法正常工作?
虽然以下内容运行良好。
(apply and (list #t #t #f))
虽然以下内容运行良好。
(apply + (list 1 3 2))
这在R5RS和R6RS中似乎都是这种情况?
(apply and (list #t #t #f))
(apply + (list 1 3 2))
这在R5RS和R6RS中似乎都是这种情况?
and
不是普通函数,因为它只会评估所需的最少参数,以确定结果是 true 还是 false。例如,如果第一个参数是 false,则无论其他参数是什么,结果都必须为 false,因此它不会评估其他参数。如果 and
是普通函数,那么它的所有参数都将首先被评估,因此 and
被作为特殊关键字制定,这就是为什么它不能作为变量传递的原因。
(define and-l (lambda x
(if (null? x)
#t
(if (car x) (apply and-l (cdr x)) #f))))
(and-l #t #t #f)
或者您可以使用 apply 过程(按照要求),例如:(apply and-l (list #t #t #f))
两个选项都可以...and
"实际上是一个宏,其定义在R5RS第4章中概述。该页面上的“库语法”表示它实现为宏。
第7.3节,派生表达式类型给出了and
宏的可能定义:(define-syntax and
(syntax-rules ()
((and) #t)
((and test) test)
((and test1 test2 ...)
(if test1 (and test2 ...) #f))))
and
作为函数参数传递给apply
。boolean/and
代替特殊形式and
。(apply boolean/and (list #t #t #f)) ;Value: #f
顺便说一下,我在Guile Scheme的过程索引中找不到任何等效的函数。
(其他答案已经解释了为什么特殊形式and
不起作用,并展示了如何编写自己的替换函数,如果在你的方言中没有这样的函数。)
(define and-l (lambda (a b) (and a b)))
你可以像这样应用:
(apply and-l (list #t #f))
这两个注意事项是:
(define (and/f . xs) (cond ((null? xs) #t) ((null? (cdr xs)) (car xs)) (else (and (car xs) (apply and/f (cdr xs))))))
- Zorf#lang racket
(require (only-in lazy [and lazy-and]))
(define (mm)
(map number? '(1 2 3)))
(printf "~a -> ~a\n" (mm) (apply lazy-and (mm)))
这会产生
(#t #t #t) -> #t
你也可以使用
(define (andApply lBoo)
(if (not (car lBoo)) #f
(if (= 1(length lBoo)) (car lBoo)
(andApply (cdr lBoo)))))
试试这个:
(define list-and (lambda (args) (and (car args) (list-and (cdr args)))))
然后你可以使用apply到列表中!
我在使用PLT-Scheme 372时也遇到了这个问题,我深入研究了and-syntax的行为,并找出了下面的代码,它的工作方式就像一个人直觉地期望(apply and lst)
返回的那样,但我还没有进行详尽的测试。
(define (list-and lst)
(cond
((null? lst) '())
((not (pair? lst)) (and lst))
((eq? (length lst) 1) (car lst))
(else
(and (car lst)
(list-and (cdr lst))))
)
)
Welcome to DrScheme, version 372 [3m].
Language: Textual (MzScheme, includes R5RS).
> (eq? (and '()) (list-and '()))
#t
> (eq? (and '#f) (list-and (list '#f)))
#t
> (eq? (and 'a) (list-and (list 'a)))
#t
> (eq? (and 'a 'b) (list-and (list 'a 'b)))
#t
> (eq? (and 'a 'b '()) (list-and (list 'a 'b '())))
#t
> (eq? (and 'a 'b '#t) (list-and (list 'a 'b '#t)))
#t
> (eq? (and 'a 'b '#f) (list-and (list 'a 'b '#f)))
#t
Welcome to DrScheme, version 372 [3m].
Language: Textual (MzScheme, includes R5RS).
> (eval (cons 'and (list ''#f ''#f ''#t)))
#f
> (eval (cons 'and (list ''a ''b ''c)))
c
(define (my-quote lst)
(map (lambda (x) `'',x) lst))
(cons 'and (my-quote (list 'a 'b 'c)))
=> '(and ''a ''b ''c)
eval
这种方法过于复杂并且不被推荐。在 Racket 中,你可以使用 andmap
来实现这个功能:(andmap values '(a b c))
=> c
。(在 Racket 中,你也可以使用 identity
替代 values
。) - C. K. Youngandmap
和identity
...您的意思是"eval..."对于像将"and"映射到"list"这样的简单任务来说太过强大,一旦出现问题,我就无法控制它了吗?(无论如何,我会记住您的建议!) - pimgeekeval
超出了我的理解范围,至少现在是这样。我会避免为了好玩而使用它...除非我对它感到自信。 :) - pimgeek