你可以做什么的例子.
(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)
有办法吗?
简短回答:是的,它有.
答案很长:
你写了:
(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而言,字符串.