Frage

Bei einer Liste von Werten möchte ich die Liste auf T reduzieren, wenn alle Elemente nicht nil sind, wenn nicht. Dies gibt mir einen Fehler:

(apply #'and (get-some-list))

Ebenso das:

(reduce #'and (get-some-list))

Dies ist das Beste, was ich mir ausgedacht habe:

[11]> (defun my-and (x y) (and x y))
MY-AND

[12]> (reduce #'my-and '(T T T T T))
T

[13]> (reduce #'my-and '(T T T T NIL))
NIL

Warum ist "#" und "ungültig? Gibt es eine idiomatischere Möglichkeit, dies in gemeinsamem Lisp zu tun?

War es hilfreich?

Lösung

#'and ist ungültig, weil and ist ein Makro, keine Funktion.

Sie können sich mit einem Lambda um eine benannte Funktion definieren:

(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t)

Es gibt keine Abkürzung wie #' obwohl.

Alternativ können Sie auch verwenden every mit der Identifizierungsfunktion als Prädikat.

Andere Tipps

Sie können jede Funktion verwenden:

(every #'identity '(T T T T T))  ->  T

und

(every #'identity '(T T T T NIL))  ->  NIL

Der wahrscheinlich effizienteste Weg ist die Verwendung von Loop:

(loop for element in '(T T T T nil) always element)  ->  NIL

Der Vorteil ist, dass keine Funktionsaufrufe über die Listenelemente erforderlich sind.

#' ist ein Lese -Makro, das sich während des Lesens des Ausdrucks in die Funktion erweitert. So #'and ist (Funktion und).

Die Funktion wird hier beschrieben: http://www.lispworks.com/documentation/hyperspec/body/s_fn.htm

Die Funktion nimmt einen Funktionsnamen oder einen Lambda -Ausdruck an und gibt das entsprechende Funktionsobjekt zurück.

Und ist hier definiert: http://www.lispworks.com/documentation/hyperspec/body/m_and.htm

Es heißt das und ist ein Makro, keine Funktion. Die Folge ist, dass (Funktion und) nicht funktioniert, da Funktion eine Funktion und kein Makro benötigt, um das entsprechende Funktionsobjekt zurückzugeben. Wie Sepp2k in seiner Antwort beschreibt, können Sie eine Funktion mit Lambda erstellen und das Makro und diese Funktion verwenden. Makros können nicht als Werte übergeben und später über Funcall oder Anwendung aufgerufen werden. Dies funktioniert nur mit Funktionen.

Diese Lösung ist geschrieben als

(reduce (lambda (x y) (and x y)) (get-some-list))

Lambda ist ein Makro, das sich erweitert (lambda (...) ...) hinein (function (lambda (...) ...)).

Also oben ist wirklich:

(reduce (function (lambda (x y) (and x y))) (get-some-list))

die geschrieben werden können als

(reduce #'(lambda (x y) (and x y)) (get-some-list))

Funktion wird benötigt, da ein gemeinsames Lisp zwischen dem Namespace für Werte und Funktionen einen Unterschied macht. Reduzierung muss die Funktion als Argument nach Wert übergeben lassen. Daher müssen wir die Funktion aus dem Funktionsnamespace abrufen - was der Zweck der Funktion ist. Wann immer wir ein Funktionsobjekt übergeben wollen, müssen wir es aus dem Funktionsnamespace erhalten.

Zum Beispiel bei einer lokalen Funktion:

(flet ((my-and (x y) (and x y)))
  #'my-and)

Lambda als Bequemlichkeitsmakro, das sich in (Funktion (Lambda ...)) ausdehnt, wurde während des Entwurfs von gemeinsamem Lisp hinzugefügt.

Sie können das Symbol "Sharp-Quote" nur mit gewöhnlichen Funktionen verwenden.

Note that only ordinary functions can be quoted with #’. It is an error to
quote a macro function or special function this way, or to quote a symbol with
#’ if that symbol does not name a function.

> #’if
Error: IF is not an ordinary function.

Common Lisp: Eine sanfte Einführung in die symbolische Berechnung, Seite 202

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top