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

mhb*_*mhb 7 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" 
Run Code Online (Sandbox Code Playgroud)

它也适用于一般的'字符串类型.

(defmethod some-fn ((num string))
  (print "a string"))
(some-fn "asrt")
"a string"
Run Code Online (Sandbox Code Playgroud)

但是,没有特定的字符串

(defmethod some-fn ((num (eql "A")))
  (print "a specifict string")))     
(some-fn "A")
  => "A string"
Run Code Online (Sandbox Code Playgroud)

我想它不起作用,因为eql不能以字符串的方式工作.

(eql "a" "a") => nil
Run Code Online (Sandbox Code Playgroud)

有办法吗?

Rai*_*wig 7

简短回答:是的,它有.

答案很长:

你写了:

(defmethod some-fn ((num (eql "A")) (print "a specifict string")))
=> doesn't compile
Run Code Online (Sandbox Code Playgroud)

那是因为你的语法错了.它应该是:

(defmethod some-fn ((num (eql "A"))) (print "a specific string"))
=> does compile
Run Code Online (Sandbox Code Playgroud)

通常将其格式化为:

(defmethod some-fn ((num (eql "A")))
  (print "a specifict string"))
Run Code Online (Sandbox Code Playgroud)

如果你以这种方式格式化并使用你喜欢的编辑器的内置缩进工具,你会发现缩进对你的代码来说是错误的:

(defmethod some-fn ((num (eql "A"))
                    (print "a specifict string")))
Run Code Online (Sandbox Code Playgroud)

它也可能有助于尝试理解编译器显示的错误消息.

回到主题:

您可以在CLOS中将字符串用作任何其他Lisp对象以进行EQL调度.

只是有许多可能的字符串看起来像"A"和EQL比较身份(数字和字符除外).EQL不会按字符比较字符串.

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

如果在命令行中输入

(some-fn "A")
Run Code Online (Sandbox Code Playgroud)

它不会触发EQL调度.

但这可以按预期工作:

(defparameter *a-string* "A")

(defmethod some-fn ((num (eql *a-string*)))
  (print "a specific string")))
Run Code Online (Sandbox Code Playgroud)

然后

(some-fn *a-string*)
Run Code Online (Sandbox Code Playgroud)

您需要确保变量具有值.在评估DEFMETHOD表单的宏扩展时,将评估变量.然后,该值是用于EQL调度的对象.

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

摘要:

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