Does CLOS have special line dispatching?

Examples of what you can do.

(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" 

It also works with a generic string type.

 (defmethod some-fn ((num string)) (print "a string")) (some-fn "asrt") "a string" 

Not with a specific line however

 (defmethod some-fn ((num (eql "A"))) (print "a specifict string"))) (some-fn "A") => "A string" 

I assume this will not work, because eql does not work with strings the way it is needed to work.

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

Is there any way to do this?

+6
common-lisp
source share
2 answers

Short answer: Yes, it does.

Long answer:

You wrote:

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

This is because you received the wrong syntax . It should be:

 (defmethod some-fn ((num (eql "A"))) (print "a specific string")) => does compile 

Usually formatted as:

 (defmethod some-fn ((num (eql "A"))) (print "a specifict string")) 

If you format it this way and use the indent tool of your favorite editor, you will see that the indentation does not look right for your code:

 (defmethod some-fn ((num (eql "A")) (print "a specifict string"))) 

It may also help to try to understand the error message shown by the compiler.

Back to the topic:

You can use strings like any other Lisp object to send EQL to CLOS.

There are simply many possible lines that look like "A", and EQL is compared for identification (with the exception for numbers and characters). EQL does not compare strings by its characters.

Usually (EQL "A" "A") returns NIL. (Lateral note: in fact, in the code compiled by the compiler, this expression could theoretically be T. Since the compiler is allowed to reuse data objects to save space in the compiled code. Here we have literals, data objects.)

If you type on the command line

 (some-fn "A") 

It does not initiate EQL submission.

But this works as expected:

 (defparameter *a-string* "A") (defmethod some-fn ((num (eql *a-string*))) (print "a specific string"))) 

and then

 (some-fn *a-string*) 

You need to make sure the variable matters. The variable is evaluated when the macro decomposition of the DEFMETHOD form is computed. Then the value is the object that is used to send EQL.

As Dirk said in his answer, you can use characters. The purpose of characters is that (EQL '| A |' | A |) is usually T. Characters are created by EQ during the reading process.

Summary:

Sending EQL row by row works in CLOS. For practical use, you need to call the function with the same, from the point of view of EQL, string.

+7
source share

Unfortunately, as far as I know. The eql specialist uses only eql for comparison (which is essentially a pointer mapping for strings). To compare the contents of strings, you need a specialized equal (or equalp ) specialist who does not exist.

If you have only a very small set of strings that you need to specialize in, you can use the keywords:

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

which you call with

 (operation (intern ... :keyword)) 
+4
source share

All Articles