Wie man die Funktion als Argument in elisp übergibt

8

Ich lese kürzlich SICP, um Lisp-Programmierung zu lernen.

Das Buch enthält ein Beispiel für die Erstellung einer Funktionssumme auf hoher Ebene ( siehe unten).

 (define (sum term a next b)
   ...
   (term a)
   ...
   (next a)
   ...

In dieser Funktion sind term und next Funktionen.

Ich möchte die gleiche Funktion in elisp wie folgt schreiben.

 (defun sum (term a next b)
    ....
    (funcall term a)
    ...
    (func next a)
    ....

Dann definiere ich einige Testfunktionen, um die Summe zu testen

 (defun inc-test (x) (+ x 1))

 sum inc-test 1 inc-test 10 

aber es zeigt Fehler wie diesen: Ungültige Funktion: inc-test

Kann mir jemand anrufen, wie ich das Problem beheben kann, da ich neu bei elisp bin? sehr schätzen

Luis404
quelle
Wie rufst du an sum?
Dan
Hallo, fügen Sie das aufrufende Beispiel hinzu
Luis404
3
Emacs Lisp hat zwei Namespces für Funktionen und für Variablen. Dies bedeutet, dass inc-testin Ihrem letzten Beispiel eine Variable verwendet wird, diese jedoch nicht als Variable definiert ist (es handelt sich um eine Funktion). Sie müssen entweder ein Symbol oder eine Funktionsreferenz an übergeben funcall. Daher besteht eine Möglichkeit, Ihren Code zu reparieren, darin, ihn 'inc-testanstelle von inc-test(beachten Sie das Zitat) zu übergeben.
wvxvw
meinst du das: summe 'inc-test 1' inc-test 10 ??? habe diesen Fehler bekommen: Verwendung: Summe: (TERM A NEXT B)
Luis404
3
Die beiden Namespaces gegenüber einem Problem sind einer der großen Unterschiede zwischen elisp und common lisp einerseits und dem Schema andererseits. Sie werden verwirrt sein, wenn Sie SICP lesen und in einem lisp-2 üben (wie die Art mit separaten Namensräumen für Variablen und Funktionen genannt wird). Vielleicht sollten Sie eine tatsächliche Schemaimplementierung zum Spielen bekommen?
Harald Hanche-Olsen

Antworten:

6

Um zu rekapitulieren, was in den Kommentaren steht, funcallwird das Argument aufgehoben (indem nur auf das Argument zugegriffen wird). Zuvor müssen wir außerdem sicherstellen, dass wir nicht versuchen, den Wert des Funktionsnamenparameters auszuwerten oder darauf zuzugreifen, der beim Aufruf der Funktion übergeben wird.

Daher scheint eine akzeptable Antwort zu sein:

(defun sum (term a next b)
    (funcall term a)
    (funcall next a))

(defun inc-test (x) (+ x 1))

(sum 'inc-test 1 'inc-test 10 )

Oder im Grunde mit 'inc-testoder (quote inctest)eher als anrufen inc-test.

felsig
quelle