Common lisp CLO在字符串上有eql专门化分派吗?

Common lisp CLO在字符串上有eql专门化分派吗?,common-lisp,Common Lisp,你能做什么的例子 (defmethod some-fn ((num real)) (print "an integer")) (defmethod some-fn ((num real)) (print "a real")) (defmethod some-fn ((num (eql 0))) (print "zero")) (some-fn 19323923198319) "an integer" (some-fn 19323923198319.3) "a real" (som

你能做什么的例子

(defmethod some-fn ((num real))
   (print "an integer"))
(defmethod some-fn ((num real))
  (print "a real"))
(defmethod some-fn ((num (eql 0)))
  (print "zero"))

(some-fn 19323923198319)
"an integer"
(some-fn 19323923198319.3)
"a real"
(some-fn 0)
"zero" 
它也适用于一般的“字符串类型”

(defmethod some-fn ((num string))
  (print "a string"))
(some-fn "asrt")
"a string"
但是,不使用特定字符串

(defmethod some-fn ((num (eql "A")))
  (print "a specifict string")))     
(some-fn "A")
  => "A string"
我认为它不起作用,因为eql对字符串的处理方式与它的工作方式不同

(eql "a" "a") => nil

有办法吗?

不幸的是,据我所知,没有办法。
eql
specializer仅使用
eql
进行比较(本质上是字符串的指针比较)。为了比较字符串的内容,您需要一个不存在的
equal
(或
equalp
)专用程序

如果你只需要很小的一组字符串,你可以考虑使用关键词:

(defmethod operation ((arg (eql ':tag-1))) ...)
(defmethod operation ((arg (eql ':tag-2))) ...)
你会用它打电话吗

(operation (intern ... :keyword))

简短回答:是的,它有。

长答覆:

你写道:

(defmethod some-fn ((num (eql "A")) (print "a specifict string")))
=> doesn't compile
这是因为语法错误。应该是:

(defmethod some-fn ((num (eql "A"))) (print "a specific string"))
=> does compile
通常格式为:

(defmethod some-fn ((num (eql "A")))
  (print "a specifict string"))
如果您以这种方式格式化它,并使用您喜爱的编辑器的内置缩进工具,您将看到缩进对于您的代码来说是错误的:

(defmethod some-fn ((num (eql "A"))
                    (print "a specifict string")))
尝试理解编译器显示的错误消息也会有所帮助

回到主题:

您可以将字符串用作CLOS中EQL分派的任何其他Lisp对象

只是有许多可能的字符串看起来像“A”,EQL比较标识(数字和字符除外)。EQL不按字符串的字符进行比较

通常(EQL“A”“A”)返回NIL。(旁注:实际上,在编译器编译的代码中,这个表达式理论上可以是T。因为编译器可以重用数据对象以节省编译代码中的空间。这里我们有文字字符串和数据对象。)

如果在命令行中输入

(some-fn "A")
它不会触发EQL调度

但这是意料之中的:

(defparameter *a-string* "A")

(defmethod some-fn ((num (eql *a-string*)))
  (print "a specific string")))
然后

(some-fn *a-string*)
您需要确保变量有一个值。当计算DEFMETHOD窗体的宏展开时,将计算该变量。然后,该值是用于EQL分派的对象

正如德克在他的回答中提到的,一个人可以使用符号。符号的用途是(EQL’| A |’| A |)通常是T。符号在阅读过程中被设置为EQ

摘要:


字符串上的EQL调度在CLOS中工作。为了实际使用,您需要使用相同的函数调用函数,即EQL、string。

Ops。甚至没有注意到语法错误。抢手货从技术上讲,使用相同的字符串实例(与“具有相同内容的字符串”相反)相当于手动执行某种类型的实习/统一,如果您的字符串来自外部源(例如,从文件或类似文件中读取),这可能会使在此处使用纯字符串变得不切实际。是的,我复制错了。我正在使用emacs等。。。这是一个朋友提出的问题,我无法回答。我喜欢使用defparam来修复它。这完全是可移植的吗?@mhb:是的,应该是可移植的。不需要引用关键字,它们会自行评估。@Vatine:这是一种习惯。我甚至经常引用
nil
(或
()
),这取决于使用情况(例如,在
:initform
中,我应该寻求专业帮助吗?:-)