2010-03-29 3 views
6

Przykłady tego, co możesz zrobić.Czy CLOS ma wysyłać specjalizację eql na ciągi?

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

Działa również z ogólnym "typem ciąg.

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

Nie z określonym ciągiem jednak

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

sobie wyobrazić, że nie działa, ponieważ eql nie działa na ciągi w sposób, który byłby niezbędny do jego pracy.

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

Czy jest jakiś sposób na zrobienie tego?

Odpowiedz

7

Krótka odpowiedź: Tak , to ma.

Długa odpowiedź:

Napisałeś:

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

To dlatego, że dostał składnia złego. Powinno być:

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

który jest zwykle sformatowane jako:

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

przypadku sformatowania to w ten sposób i korzystać z wbudowanego narzędzia wcięcia swojego ulubionego edytora, można zobaczyć, że wygląda wcięć źle o kodzie:

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

To również może pomóc, aby spróbować zrozumieć komunikatu o błędzie przedstawionego przez kompilator.

Powrót do tematu:

Można użyć ciągi jak każdy inny Lisp obiektu dla EQL przeciągu CLOSA.

Po prostu istnieje wiele możliwych ciągów, które wyglądają jak "A", a EQL porównuje tożsamość (z wyjątkiem liczb i znaków). EQL nie porównuje łańcuchów znaków według ich znaków.

Zazwyczaj (EQL "A" "A") zwraca NIL. (Nota boczna: W rzeczywistości w kodzie skompilowanym przez kompilator, to wyrażenie teoretycznie może być T. Ponieważ kompilator może ponownie wykorzystywać obiekty danych, aby zaoszczędzić miejsce w skompilowanym kodzie.Tutaj mamy dosłowne ciągi, obiekty danych).

Jeśli wpiszesz w wierszu poleceń

(some-fn "A") 

nie spowoduje wysyłkę eql.

Ale to działa zgodnie z oczekiwaniami:

(defparameter *a-string* "A") 

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

a następnie

(some-fn *a-string*) 

Musisz upewnić się, że zmienna ma wartość. Zmienna jest oceniana, gdy oceniane jest rozszerzenie makra formularza DEFMETHOD. Wartością jest wówczas obiekt, który jest używany do wysyłki EQL.

Jak wspomniał Dirk w swojej odpowiedzi, można używać symboli. Celem symboli jest to, że (EQL "| A |" | A |) jest zwykle T. Symbole są tworzone EQ podczas procesu czytania.

Podsumowanie:

EQL wysyłka w ciągu strun działa w CLOS. W celu praktycznego użycia, musisz wywołać funkcję z tym samym, pod względem EQL, ciągiem znaków.

+0

Ops. Nawet nie zauważyłem błędu składni. Dobry połów. Technicznie, użycie tej samej instancji napisu (w przeciwieństwie do "ciągu o tej samej zawartości") oznacza ręczne przejście do jakiegoś polecenia/unifikacji, jeśli twoje ciągi pochodzą z zewnętrznych źródeł (powiedzmy, odczytane z pliku lub plików), które mogą renderowanie przy użyciu zwykłych łańcuchów jest niepraktyczne. – Dirk

+0

Yup, skopiowałem to źle. Używam emacs etc ... To było pytanie od znajomego, na które nie mogłem odpowiedzieć. Lubię korzystać z defparam, aby to naprawić. Czy to jest całkowicie przenośne? – mhb

+0

@mhb: tak, powinno być przenośne –

4

Niestety nie tak daleko, jak wiem. Specjalizator eql używa tylko porównania eql (co jest w istocie porównaniem do łańcuchów). Aby porównać zawartość napisów, potrzebujesz specjalisty equal (lub equalp), który nie istnieje.

Jeśli masz tylko bardzo niewielki zestaw strun trzeba specjalizować się dalej, można rozważyć użycie słowa kluczowe:

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

który można nazwać z

(operation (intern ... :keyword)) 
+1

Nie trzeba cytować słów kluczowych, oceniają same siebie. – Vatine

+0

@Vatine: To nawyk. Często nawet cytuję 'nil' (lub'() ') w zależności od użycia (na przykład w': initform' of 'defclass' lub 'defstruct'.) Czy powinienem szukać profesjonalnej pomocy? :-) – Dirk

Powiązane problemy