2008-11-17 18 views
9

Ich habe eine große Liste von globalen Variablen, die jeweils ihre eigene Setup-Funktion haben. Mein Ziel ist es, diese Liste zu durchlaufen, die Setup-Funktion jedes Elements aufzurufen und einige Statistiken für die Daten zu generieren, die in die passende Variable geladen wurden. Was ich jetzt versuche, funktioniert jedoch nicht und ich brauche Hilfe, damit mein Programm die Setup-Funktionen aufruft.Funktionsnamen als Strings in Lisp?

Die globalen Variablen und ihre Setup-Funktionen unterscheiden zwischen Groß- und Kleinschreibung, da sie aus XML stammen und für die Eindeutigkeit erforderlich sind.

Die Daten sieht etwa so aus:

'(ABCD ABC\d AB\c\d ...) 

und die Setup-Funktionen wie folgt aussehen:

(defun setup_ABCD... 
(defun setup_ABC\d... 

Ich habe versucht, sie zusammen und drehen die resultierende Zeichenfolge in eine Funktion, verketten Dies stört jedoch den Namespace der zuvor geladenen Setup-Funktion. Hier ist, wie ich versucht, das umzusetzen:

(make-symbol (concatenate 'string "setup_" (symbol-name(first '(abc\d))))) 

Aber mit funcall auf das nicht funktioniert. Wie kann ich eine aufrufbare Funktion erhalten?

+0

Wenn Nirgends die Antwort des Mannes funktioniert, wäre es schön, sie als akzeptiert zu markieren, indem Sie auf das Häkchen klicken. – Pablo

+0

Der Name Standard in Lisp ist Bindestriche, keine Unterstriche. Außerdem liest der Leser alle Symbole intern ein, und der Standard besteht darin, sie in Kleinbuchstaben zu schreiben. Daher lautet die Standardmethode zum Aufrufen der Setup-Funktion 'setup-abcd'. – Svante

+0

Entschuldigung für die verspätete Zecke! Auch die Setup-Fns wurden von einem Nicht-Lisper geschrieben. Ich habe ihm seitdem meine Kopie von Norvigs Lisp/AI-Buch ausgeliehen. – ktdh

Antwort

12

Es ist, weil MAKE-SYMBOL ein nicht durchgeblendete Symbol zurückgibt. Sie sollten stattdessen INTERN verwenden.

+0

BINGO! Ich hatte gehofft, es wäre so einfach. Danke, vielen Dank! – ktdh

+0

Nun, Chet, nächster Schritt: Akzeptiere die Antwort. – Svante

+0

können Sie ein Beispiel geben, um das für mich zu zementieren, bin ich nur noch ein wenig verwirrt :( – ajivani

0

Ich würde entweder INTERN verwenden oder (möglicherweise müssen Sie profilieren, um 100% sicher zu sein, dass es hilfreich ist) eine Hilfsfunktion, die die String-Verkettung und die erste Suche durchführt, dann speichert das Ergebnis in einer Hashtabelle (keyed aus dem ursprünglichen Symbol). Das könnte schneller als eine reine INTERN/CONCATENATE-Lösung sein, würde möglicherweise weniger transienten Abfall erzeugen, würde aber am Ende mehr Langzeitspeicher verwenden.

Etwas entlang der Linien von:

 
(defvar *symbol-function-map* (make-hash-table)) 

(defun lookup-symbol (symbol) 
    (or (gethash symbol *symbol-function-map*) 
     (let ((function-name (intern (concatenate 'string "setup_" (symbol-name symbol))))) 
     (setf (gethash symbol *symbol-function-map*) (symbol-function function-name))))) 

Wenn Sie den Namen der Funktion erfordern, anstatt die Funktion selbst, um den Anruf zu SYMBOL FUNKTIONS auslassen.

0
(funcall (read-from-string (concatenate 'string "setup_" (symbol-name(first '(abc\d)))))) 

funktioniert auch.