我正在使用map
来测试值列表,以查看它们是否具有给定属性。然后,我想看看他们是否都拥有该属性并返回true
iff他们都这样做。
所以我的第一个想法是将列表and
作为(and (list #t #t #f))
,但这似乎将整个(#t #t #f)
视为布尔值true并返回它。
所以,我想我可以使用foldl
。我知道(foldl + 0 (list 1 2 3))
有效,我认为(foldl and #t (list #t #t #f))
也应该有效......但事实并非如此。
在DrRacket中(使用#lang racket
),我收到错误“and: bad syntax in: and
”,这不是太有用,而是Repl.it(使用BiWaScheme })我收到错误“Error: #<Syntax and> is not a function
”。
所以,我猜测and
是一个宏?支持这一点似乎我只是评估+
我得到#<procedure:+>
,但对于and
我得到and: bad syntax in: and
(扼杀,xor
是一个程序但{{1} }},or
和nor
不是)。
那么,它是一个宏还是什么(可能是为了促进短路)?如果是这样,将执行“和”操作的布尔函数是什么?
答案 0 :(得分:7)
其他答案已经解释了如何使用and
“好像”它是一个函数,但and
是一个宏的原因是支持你习惯的“短路”行为来自其他语言。例如,(and #f (display "blah"))
不会打印任何内容,因为and
会在看到错误值时立即停止。如果and
是一个函数,则在调用它之前必须对它的两个参数进行求值,然后display
无论如何都会发生。
答案 1 :(得分:6)
是的,and
是一个宏。但你可以用
(lambda (x y) (and x y))
,如
(foldl (lambda (x y) (and x y)) #t your-list)
答案 2 :(得分:1)
其他答案已经解释了为什么and
不是直接的函数,但是语言设计的根本原因还有待揭示。
有核心原因:
and
expression in Scheme需要支持对操作数进行“短路”评估(“在第一个评估结果为假值的表达式之后”“未评估任何剩余表达式”),例如{{3} },并非所有操作数都必须在调用中求值。这些使用过程和支持短路评估的要求在逻辑上是不一致的,因此您不能在语言中将它们共存。宏可以支持非严格评估non-strict evaluation,因此就在这里。
但是,以上限制是由于Scheme的设计选择造成的。功能和非严格评估的概念本质上并不冲突。使用提供支持非严格评估的“功能”(Scheme的过程除外)的语言,可以实际实现类似的构造。值得注意的是,by expansion作为类Scheme的派生,既提供了应用组合器(如Scheme的过程),又提供了可操作的组合器(宏的替换,但是一流的过程,例如,允许作为操作数传递给另一个组合器) ,可以统称为“功能”。该语言的标准派生(非基本组合器)包括 both $and?
(作为Scheme的and
宏,具有短路评估功能)和and?
(保证操作数总是先被评估的应用程序,就像普通的严格评估函数一样)。作为实现,Klisp提供了$and?
的派生作为the Kernel language中的区别示例。