您可以做的例子。
(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
有办法吗?
答案 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))