2016-03-22 15 views
2

Ich habe vor kurzem angefangen, CL zu lernen, und ich versuche herauszufinden, ob ich einen Wert auf ein Symbol im Funktionsnamensraum setzen kann.Kann ich eine Funktion im Funktionsnamensraum durch ihren Wert definieren?

Ich möchte nur Funktionen in Bezug auf die Zusammensetzung der Funktionen definieren, oder einfach durch eine vorhandene Funktion (z. B. musste ich identity zweimal in einem Spielzeug "Hello, World!" - Level-Projekt) neu schreiben. Ich bin mir nicht sicher, ob es überhaupt möglich ist, da es die Namespace-Trennung (zumindest ohne Durchsetzung) durchbrechen könnte. Ich habe auch versucht, macroexpand was defun tatsächlich tut; Es ist zu kryptisch für mich als Anfänger, aber es scheint, als ob der Kern davon eingebaut ist (ich benutze SBCL).

Also z.B. anstatt zu sagen:

(defun myfn (x) x) 

Ich würde lieber nur sagen:

(def..? myfn identity) 

Wenn ich das nicht tun kann, wie kann ich diese Klasse von Code Doppelarbeit zu vermeiden? (die Funktionen enthält, die durch die Funktionszusammensetzung erstellt werden und nicht nur Synonyme erstellen).

+0

Nur eine Idee, Sie könnten ein Makro hinzufügen, das auf 'erweitert (defun myfun (& Restargumente) (gelten Identität Args)). Natürlich könnte man in einem Lisp-1 einfach '(definiere myfn identity)'. – Cactus

+2

Sehen Sie sich auch einige der Funktionen an, die mit dem Duplikat verknüpft sind. Es gibt viele nützliche Informationen, die herumfliegen. Die eine mit dem Titel ** warum defun ist nicht das gleiche wie (setq )? ** hat eine gute Diskussion. –

+1

Um klar zu sein, können Sie den Funktionswert eines Symbols auch mit der Notation '# 'abrufen. Das heißt, Sie müssen nicht 'tun (((id (lambda (x) x))) (komponieren id ...))'. Sie können einfach '(lassen Sie ((ID # 'Identität)) (komponieren ID ...))' oder '(komponieren #' Identität ...)'. –

Antwort

5

Das ist für Funktionen möglich ist, um Symbole gebunden, in der aktuellen Umgebung:

(setf (symbol-function 'myfn) #'identity) 

Es gibt auch (setf FDEFINTION) die meistens tut das gleiche, aber unterstützt auch setf Funktionen.

Man kann es nicht für lexikalisch gebundene Funktionen tun (durch FLET und LABELS).

Beispiel, wie eine Symbolfunktion einstellen (setf fdefinition)

CL-USER 11 > (setf (fdefinition 'myfn) #'identity) 
#<Function IDENTITY 410003F974> 

CL-USER 12 > (myfn 10) 
10 

Weitere Ausführungen mit

Beachten Sie, dass es funktioniert, dass in der aktuellen Umgebung. So

(defun myfn (x) x) 

könnte durch so etwas wie

(eval-when (:compile-toplevel :load-toplevel :execute) 
    (setf (fdefinition 'myfn) #'identity)) 

Tha Vorteil ersetzt werden: die Funktion wie gewohnt während der Kompilierung bekannt ist.

Eines der Dinge im Auge zu behalten:

Das Symbol Objekt kann einige Informationen tragen. Zum Beispiel Name des ursprüngliche Funktion, wenn gab es ein:

CL-USER 13 > #'identity 
#<Function IDENTITY 410003F974> 

die Funktionszelle eines Symbol einstellen, ändert sich nicht, dass:

CL-USER 14 > #'myfn 
#<Function IDENTITY 410003F974> 

Es ist das gleiche Funktion Objekt mit seinem ursprünglichen internen Namen.Man kann in der Lage sein, diesen Namen zugreifen zu können, aber man kann es nicht ändern:

CL-USER 18 > (nth-value 2 (function-lambda-expression #'identity)) 
IDENTITY 

Es gibt auch ein Problem mit sich selbst rekursive Funktionen:

CL-USER 19 > (defun foo (n) 
       (if (zerop n) 
        1 
       (* n (foo (1- n))))) ; here foo calls the function foo 
FOO 

jetzt setzen wir BAR die Funktion zu verwenden, FOO

CL-USER 20 > (setf (symbol-function 'bar) #'foo) 
#<interpreted function FOO 4060004084> 


CL-USER 21 > (bar 10) 
3628800 

Hier definieren wir FOO:

CL-USER 22 > (defun foo (n) 
       (if (zerop n) 
        1 
       (+ n (foo (1- n))))) 
FOO 

BAR verwendet immer noch die alte FOO, die möglicherweise die neue FOO aufrufen oder nicht.

CL-USER 23 > (bar 10) 
460 

OOPS! Wir haben FOO geändert, aber es hat seltsame Auswirkungen auf BAR: Die erste Iteration ist der alte FOO und der nächste rekursive Aufruf ist der neue FOO.

BAR und FOO sind zwei verschiedene Versionen der gleichen Funktion. Aber beide nennen die Funktion FOO, die die alte oder die neue Funktion sein kann - je nachdem, wie Sie den Code interpretieren oder übersetzen.

Verwandte Themen