Betrachten Sie dieses Javascript:
%Vor%Bitte ignorieren Sie die Tatsache, dass es von zweifelhafter Verwendung und Methodologie ist, gefährlich, schwer in einer großen Codebasis zu folgen, und so weiter. Mit dieser Funktion können Sie die Funktion im laufenden Betrieb basierend auf Eingaben des Benutzers ändern. Ich habe das nicht gezeigt, aber ich könnte es genauso leicht haben.
Ich hoffe, du kannst mir zeigen, wie man das in Lispeln macht. Ich habe viele Tutorials gelesen und viel über Makros gelesen, hat eine umfassendere Frage gestellt , hat viele Dinge ausprobiert, ist aber letztendlich zu kurz gekommen.
Ich möchte wissen, wie ich in lisp diese Funktion zur Laufzeit ändern kann , um stattdessen 5 hinzuzufügen. Oder was auch immer der Benutzer eingeben mag.
%Vor%Ich suche kein Currying ! Ich weiß, dass ich das tun kann:
%Vor% Aber das schafft eine Funktionsfabrik.
Ich benutze ein einfaches Beispiel, weil ich den harten Weg auf etwas einfach genug verstehen will.
Bearbeiten Vielen Dank für Ihre Antworten. Ich denke, mein großer Haken an Makros (so wie ich sie verstehe) ist, dass ich keinen gesehen habe, der die Modifikation vollständig von der Schrift trennt. Das Javascript-Beispiel ist einfach - Sie können jedoch komplexere Umschreibungen basierend auf Benutzereingaben vornehmen.
Die Makros, die ich gesehen habe, basieren alle auf der "Kompilierzeit" (oder der Zeit, die ich vom Programmierer geschrieben habe). Wie in C ++ können Sie keinen dynamischen Vorlagenparameter haben - er muss zur Kompilierzeit bekannt sein.
(Es scheint) In Lispeln können Sie eine Prozedur zur Laufzeit nicht grundlegend ändern, so wie Sie es in Javascript können, weil Sie die Quelle verloren haben. Sie können es zwar auswerten und neu definieren, aber Sie können nicht durch die Elemente der Liste iterieren (die Liste ist die Funktionsdefinition), jedes Element prüfen und entscheiden, ob es geändert werden soll oder nicht. Die Ausnahme scheinen die Beispiele in Rainers Antwort zu sein, die wackeligen Boden haben.
Der schwierige Teil ist, dass Common Lisp (und einige andere Lisps) den Quellcode loswerden. Vor allem, wenn ein Compiler beteiligt ist. Standardmäßig ist der Quellcode weg und es bleibt nur noch der Maschinencode. Wie kann ich die Lisp-Quelle und in welcher Form wiederherstellen?
Der Grund dafür: Warum sollte ein CL-Programm benötigt werden, um die Quelle zu behalten? Es könnte vollständig kompiliert werden, um Code oder C-Code zu bearbeiten, und zur Laufzeit keinen Compiler / EVAL haben. Das Programm könnte ohne große Entwicklungsumgebung laufen (kein Compiler, etc.). Die Common-Lisp-Umgebung sollte außerdem nicht erforderlich sein, um Code zu einem rekonstruierten Quellcode "kompilieren" zu können.
Auch ist es generell kompliziert.
%Vor%Was ist die Quelle von oben und wie könnten Sie STEP ändern? Die Funktion hängt von der lexikalischen Bindung ab.
Eine weitere Komplikation:
%Vor%Wie kann ich das wiederherstellen? Jedes Mal, wenn Lisp den Quelltext liest, wird eine Zufallszahl gelesen.
Eine weitere Komplikation:
%Vor%Sie können den Funktionswert mit einer beliebig berechneten Funktion oder einer vordefinierten Funktion (wie SIN) einstellen. Wie werden diese wiederhergestellt, wenn sie in Maschinencode kompiliert, als Maschinencode usw. geladen werden?
Wenn eine Common-Lisp-Implementierung Quellcode enthält, ruft FUNCTION-LAMBDA-EXPRESSION ihn ab.
Dafür gibt es zwei Möglichkeiten:
a) Teilen Sie Lisp den Quellcode mit oder erinnern Sie sich an die Quelle.
Geben Sie die Quelle an.
%Vor%Erweitertes Beispiel:
Schreibe ein Makro DEFINE, das sich die Quelle merkt und die Funktion definiert.
%Vor%Oben wird der Quellcode in die Liste der Symboleigenschaften eingefügt: SOURCE.
Nun können wir eine Funktion schreiben, die die Quelle modifiziert und kompiliert:
%Vor%Beispieldefinition:
%Vor%Beispiel umschreiben:
%Vor%b) Einige Common-Lisp-Implementierungen implementieren eine Funktion namens FUNCTION-LAMBDA-EXPRESSION (definiert in ANSI Common Lisp).
Diese Funktion gibt drei Werte zurück: die Quelle als Lisp-Daten, closure-p und den Namen. Es würde Ihnen erlauben, die Quelle zu ändern, sie zu kompilieren und den Namen mit COMPILE auf die neue Funktion zu setzen. Code Beispiel übrig als Übung.
Problem: In Common Lisp definiert das Makro DEFUN Funktionen. Was das Makro hinter den Kulissen macht (Buchführung für die IDE, Codeumschreibung, ...) ist implementierungsabhängig. Daher kann der Code, der von FUNCTION-LAMBDA-EXPRESSION zurückgegeben wird (wenn die Implementierung den Quellcode zurückgibt), für jede Implementierung anders aussehen.
Dies ist ein LispWorks Beispiel:
%Vor%So könnten Sie den Quellausdruck bearbeiten und ändern.
Die Ausnahme scheint das Beispiel zu sein in Rainers Antwort, die wackelig sind Boden.
Warum? Es ist die logische Schlussfolgerung. Sie können sich nicht darauf verlassen, dass der Compiler die Quelle beibehält, also speichern Sie sie einfach selbst.
Danach können Sie richtig mit der Definition der Funktion arbeiten (im Gegensatz zu Javascript, wo Sie einfach eine String-Repräsentation hacken, was ein Paradebeispiel für eine zittrige Sache ist).
Unser Verfahrenscode:
%Vor%Evaluiere es für eine Funktion:
%Vor%Ändern Sie es:
%Vor%Das ähnelt dem, was Sie im JavaScript-Code getan haben. Ob es eine gute Idee ist, ist nicht das, was Sie gefragt haben, also werde ich das auslassen.
(Einfache Ersetzungsprozedur, die ich ausgepackt habe:)
%Vor%Die Art, wie Sie Ihr Javascript schreiben, legt nahe, dass Sie nach einem Makro suchen:
%Vor%Das gibt Ihnen also:
%Vor%Das Makro gibt Ihnen das, was Sie wollen, da es keine Curry-Funktion ist und den Namen des Makros nicht neu schreibt, damit Sie den Änderungen folgen können (obwohl dies mit etwas Komplexem durchgeführt werden könnte), aber gibt Ihnen, was Sie wollen, in dem es Ihnen ermöglicht, die Funktion im laufenden Betrieb zu ändern.
Tags und Links lisp common-lisp