Die einfachste Lösung scheint ein Leser Makro zu sein, die .
so überlastet, dass (slot-value somebody 'name)
Meine Strategie ist somebody.name
als String lesen (wir einen nicht abbreche Makro Zeichen definieren müssen, damit der Leser tut geschrieben werden kann als .somebody.name
nicht stoppen Mitte string), und dann verarbeiten die Zeichenfolge die entsprechende (slot-value...
ich zwei Hilfsfunktionen müssen konstruieren:
(defun get-symbol (str)
"Make an uppercase symbol"
(intern (string-upcase str)))
(defun split-string (str sep &optional (start 0))
"Split a string into lists given a character separator"
(let ((end (position sep str :start start)))
(cons (subseq str start end) (if end (split-string str sep (1+ end))))))
und dann kann ich meine Leser Makro definieren:
(defun dot-reader (stream char)
(declare (ignore char))
(labels ((make-query (list)
(let ((car (car list))
(cdr (cdr list)))
(if cdr `(slot-value ,(make-query cdr) (quote ,(get-symbol car)))
(get-symbol car)))))
(make-query (nreverse (split-string (symbol-name (read stream)) #\.)))))
Schließlich muss ich diese Leser Makro registrieren:
(set-macro-character #\. #'dot-reader t)
Jetzt ist es möglich, zu schreiben:
(defmethod get-name ((somebody person) .somebody.name)
oder, wenn name
selbst eine Klasse,
(defmethod get-name ((somebody person) .somebody.name.first-name)
Eine Einschränkung ist, dass s-Ausdrücke zwischen t nicht funktioniert er Punkte, sagen
.(get-my-class).name
wird nicht funktionieren.
Danke, das ist in der Tat, was ich gesucht habe. Ich denke, ich habe das entsprechende Kapitel in Practical Common Lisp einfach nicht weit genug gelesen. Also wusste ich auch nicht, dass es Makros mit und Makros gibt. – Andrei