如果我想比较两个值是否相等,则有许多选项,例如:
eq
代码=
代表数字char-equal
代表字符string-equal
字符串eql
代码,数字和字符串equal
除了符号之外的所有内容(我希望到目前为止我能做到这一点。)
现在,作为一个Lisp初学者,我的问题是:为什么?这仅仅是出于“历史原因”还是存在所有这些可能性的真正好处?
我知道为什么 -questions总是很难回答,可能是基于意见的,但我认为(猜测)有一些最佳实践,这些实践是高级Lisp开发人员共同商定的。< / p>
答案 0 :(得分:3)
有很多因为有针对某些类型优化的专业比较函数。使用它们可能会提供更好的性能。
中读到的这条简单规则eq
比较识别相同的对象(指针相等)equal
用于看起来相同的所有内容现在有时候你想测试一个字符串是否等同于区分大小写,然后equal
不会这样做,因为&#34; test&#34;和&#34; TEST&#34;看起来不一样。 string-equal
将是正确的选择。
在比较不同类型的数字时,例如3.0和3,它们看起来不一样。但是,如果您(= 3 3.0)
T
equalp
,那么如果将fixnum转换为浮点数,则它们代表相同的值。
同样equal
与=
类似,不同之处在于字符串不区分大小写,数字类似equalp
。我不完全确定,但在我看来,第三条规则是:
因此,您只需使用那些通用的3个,但有些情况下您可能需要搜索CLHS以获取专门的相等运算符。
答案 1 :(得分:2)
您实际上可以将所有内容与eq
,eql
,equal
和equalp
进行比较。但要自己选择,需要什么:
很容易认为eq
比较指针。因此,符号(因为唯一符号只输入一次包,并且在每种情况下它的地址都相同)将返回true。
CL-USER> (eq 'a 'a)
T
接下来,不同的列表,即使包含相同的值,也不相等(以eq
表示)。它们有不同的地址,它们是不同的对象。
CL-USER> (defparameter *a* '(1 2))
*A*
CL-USER> (defparameter *b* '(1 2))
*B*
CL-USER> (eq *a* *b*)
NIL
但它并不总是正确的,例如,如果你正在处理文字对象:
CL-USER> (lambda nil '(1 2 3))
#<FUNCTION :LAMBDA NIL '(1 2 3)>
CL-USER> (eq * *)
T
虽然:
CL-USER> (eq '(1 2 3) '(1 2 3))
NIL
棘手?您可能期望包含相同数字的不同变量的值不相等,因为数字应该占用不同的内存块,但是......
CL-USER> (defparameter *c* 5)
*C*
CL-USER> (defparameter *d* 5)
*D*
CL-USER> (eq *c* *d*)
T
eq
函数的描述说明了相同的对象,因此数字5在任何地方都是相同的对象。
接下来,eql
函数在eq
上定义,在以下情况下评估t
:
eq
。并且equal
,equalp
处理视觉上相似的&#39;对象。
为什么这么多人呢?想想你自己:在像LISP这样的语言中你不明确地使用指针你可能想在列表中找到完全相同的对象(在同一地址)或任何地方。所以你需要在这个&#39;指针上运行的函数#39;水平。接下来很明显,你需要正常的&#39;比较功能和它们在这里。差异是微妙的,有点历史性,但通常有用它们。
同样重要的是要注意,这4个基本比较函数中的一些具有应用于某些类型的数据的附加含义。例如,equal
用于以区分大小写的方式比较字符串,而equalp
用不区分大小写的方式进行比较。
CL-USER> (equal "My String" "My String")
T
CL-USER> (equal "My String" "My string")
NIL
CL-USER> (equalp "My String" "My string")
T
要继续使用字符串示例,这里有许多函数,例如string=
等。为什么?那是什么&#39; The Common Lisp Cookbook&#39;表示:
如果您正在部署实现定义的字符属性,则您将要使用这些属性。在这种情况下,请查看供应商的文档。
然而,在绝大多数情况下,4个基本功能就足够了。
答案 2 :(得分:2)
基本上有两组比较:
通用比较试图为典型(主要)符号编程中的基本用例提供功能。
特定于类型的比较被认为表达(并且可能检查)参数是某种类型的。它们还提供有效的实现。添加它们是为了使这些函数可以在代码中使用,这需要扩展到或调用特定和有效的函数。