CLOS是否对字符串进行了eql特化调度?

时间:2010-03-29 20:42:43

标签: 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"
(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

有办法吗?

2 个答案:

答案 0 :(得分:7)

简短回答:是的,它有。

答案很长:

您写道:

(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调度的对象。

正如Dirk在他的回答中所提到的,人们可以使用符号。符号的目的是(EQL'| A |'| A |)通常是T.符号在读取过程中被赋予EQ。

<强>要点:

字符串上的EQL调度在CLOS中有效。对于实际应用,您需要使用相同的函数调用函数,就EQL而言,字符串。

答案 1 :(得分:4)

不幸的是,据我所知。 eql专门化程序仅使用eql进行比较(这实际上是字符串的指针比较)。为了比较字符串的内容,您需要一个equal(或equalp)专门化程序,它不存在。

如果您只需要专门研究一小组字符串,则可以考虑使用关键字:

(defmethod operation ((arg (eql ':tag-1))) ...)
(defmethod operation ((arg (eql ':tag-2))) ...)

你可以用

打电话
(operation (intern ... :keyword))