`member`返回`NIL`,即使列表中存在字符串。

问题描述 投票:0回答:2

普通Lisp。

我试图确定一个字符串是否存在于一个给定的列表中。

我的目标是要有 (member searched-string my-list)但我一直得到 NIL.

为什么 (member "foo" '("foo" "bar")) 返回 NIL?

enter image description here

lisp common-lisp
2个回答
4
投票

这是因为 (eql "foo" "foo") ; ==> nil. 虽然在CLHS中没有记载 member 用途 #'eql 作为标准测试。要让它使用 #'equal 也评价 t 的结构,显示相同的

(equal "foo" "foo") ; ==> t
(member "foo" '("foo" "bar") :test #'equal) ; ==> ("foo" "bar")

字符串是以字符向量的形式存储的,因此,除非它是同一个对象。eqeql 将评估到 nilequal 检查字符串中的所有字符是否为 eql.

注意: (eql "foo" "foo") 也可以是 t. 由于它是文数,因此是常量数据,同样的代码编译后在某些实现中只存储了 "test" 一次,使它们的指针相等(eq).


8
投票

的默认值。:test 关键字参数是 #'eql:

如果没有a :test 也不是 :test-not 参数,就像提供了一个 :test 的论点 #'eql 被提供。

17.2.1 关于测试函数的规则--满足两个参数测试的要求

字符串不是数字,也不是字符,所以两个字符串是 eql 才会 eq (相同),但在你的例子中,你可能有两个不同的字符串分配。你可以在以下地方进行优化 string= 字符串被编译器内置于其中,使它们成为 eq但这将是一个实施细节。

下面,同样的 foo 字符串用于建立列表,并作为参数给 member而调用实际上是在找值。

(let ((foo "foo"))
  (member foo (list foo "bar")))
=> ("foo" "bar")

但更多的是,你想传递一个字符串比较函数,比如: string-equal (不区分大小写)或 string= (精确的情况),或者干脆就是一个通用的平等谓词;下面两个例子都能找到sarch字符串。

(member "foo" '("foo" "bar") :test #'equal)
(member "FOO" '("foo" "bar") :test #'equalp)
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.