如果您需要使用内置等价运算符之一进行比较,您可以使用memq, memv, or member http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_428,取决于您是否想使用寻找相等性eq?, eqv?, or equal? http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.1, 分别。
> (memq 'a '(a b c))
'(a b c)
> (memq 'b '(a b c))
'(b c)
> (memq 'x '(a b c))
#f
正如您所看到的,如果这些函数找到一个元素,它们就会返回从第一个匹配元素开始的子列表。这是因为,如果您正在搜索可能包含布尔值的列表,则需要能够区分查找的情况#f
从没有找到您正在寻找的元素的情况来看。列表是一个真值(Scheme 中唯一的假值是#f
)所以你可以使用结果memq
, memv
, or member
在任何需要布尔值的上下文中,例如if
, cond
, and
, or or
表达。
> (if (memq 'a '(a b c))
"It's there! :)"
"It's not... :(")
"It's there! :)"
这三种不同的功能有什么区别?它基于他们使用哪个等价函数进行比较。eq?
(因此memq
) 测试两个对象是否是同一个底层对象;它基本上相当于指针比较(或整数情况下的直接值比较)。因此,看起来相同的两个字符串或列表可能并不相同eq?
,因为它们存储在内存中的不同位置。equal?
(因此member?
)对列表和字符串进行深度比较,因此基本上打印相同内容的任何两个项目都将是equal?
. eqv?
就好像eq?
除了数字之外几乎任何东西;对于数字,两个在数值上相等的数字总是eqv?
,但他们可能不是eq?
(这是因为 bignum 和有理数,它们的存储方式可能不会被eq?
)
> (eq? 'a 'a)
#t
> (eq? 'a 'b)
#f
> (eq? (list 'a 'b 'c) (list 'a 'b 'c))
#f
> (equal? (list 'a 'b 'c) (list 'a 'b 'c))
#t
> (eqv? (+ 1/2 1/3) (+ 1/2 1/3))
#t
(Note that some behavior of the functions is undefined by the specification, and thus may differ from implementation to implementation; I have included examples that should work in any R5RS compatible Scheme that implements exact rational numbers)
如果您需要使用与内置谓词不同的等价谓词来搜索列表中的项目,那么您可能需要find http://srfi.schemers.org/srfi-1/srfi-1.html#find or find-tail http://srfi.schemers.org/srfi-1/srfi-1.html#find-tail来自 SRFI-1:
> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6))
'(4 5 6)