"Und" vs "wann" für Bedingungen

13

Dies ist eine Fortsetzung der Kommentare zu dieser Antwort . Die folgenden Codebits scheinen äquivalent zu sein:

(and a b)

(when a b)

Natürlich andkönnen Sie mehr Bedingungen stellen: (and a b c d)bedeutet(when (and a b c) d)

Ich neige dazu, whennur Verzweigungen auszudrücken. Gibt es tatsächliche Unterschiede? Ist es besser das eine oder andere zu benutzen?

Ich habe keine Emacs C-Quelle zur Hand; andist eine C-Funktion; whenist ein Makro, das erweitert ifwird und selbst eine C-Funktion ist.

Clément
quelle
"Natürlich und Lässt" sollte "Natürlich" und "Lässt" sein, aber das ist nur eine Änderung von 2 Zeichen und keine erlaubte Änderung. Es gibt keine Außerkraftsetzung.
Harvey

Antworten:

17

TL; DR: when handelt von Nebenwirkungen, andist für reine Boolesche Ausdrücke.

Wie Sie bemerkt haben, andund whenunterscheiden sich nur in der Syntax, sind aber ansonsten völlig gleichwertig.

Der syntaktische Unterschied ist jedoch sehr wichtig: Es wird whenein Implizit prognum alle außer den ersten Argumentformen gewickelt. prognist ein von Natur aus unerlässliches Merkmal: Es bewertet alle Körperformen außer der allerletzten nur auf ihre Nebenwirkungen und verwirft dabei den jeweils zurückgegebenen Wert.

Als solches whenist es auch eine zwingende Form: Ihr Hauptzweck ist es, nebenwirkende Formen zu verpacken, da nur der Wert der allerletzten Form tatsächlich für den Körper von Bedeutung ist.

andAuf der anderen Seite handelt es sich um eine reine Funktion, deren Hauptzweck darin besteht, die Rückgabewerte der angegebenen Argumentformen zu betrachten: Sofern Sie prognkeines der Argumente explizit umbrechen , ist der Wert jeder Argumentform wichtig, und kein Wert wird jemals ignoriert .

Daher ist der eigentliche Unterschied zwischen andund whenstilistisch: Sie verwenden ihn andfür reine boolesche Ausdrücke und whenum nebenwirkende Formen zu schützen.

Daher sind dies schlechte Stile:

;; `when' used for a pure boolean expression
(let ((use-buffer (when (buffer-live-p buffer)
                    (file-exists-p (buffer-file-name buffer)))))
  ...)

;; `and' used as guard around a side-effecting form
(and (buffer-file-name buffer) (write-region nil nil (buffer-file-name buffer)))

Und das sind gute:

(let ((use-buffer (and (buffer-live-p buffer)
                       (file-exists-p (buffer-file-name buffer)))))
  ...)

(when (buffer-file-name buffer)
 (write-region nil nil (buffer-file-name buffer)))

Ich weiß, dass einige Leute darüber nicht einverstanden sind und gerne andNebenwirkungen abwehren, aber ich denke, dass dies wirklich ein schlechter Stil ist. Wir haben diese verschiedenen Formen aus einem Grund: Syntax zählt . Andernfalls würden wir alle nur ifdie einzige Bedingungsform verwenden , die Sie in Emacs Lisp semantisch wirklich benötigen. Alle anderen booleschen und bedingten Formen können in Bezug auf geschrieben werden if.

Mondhorn
quelle
2
IMO (dh im Stil ich verwende), andist über das Sorgen über den Rückgabewert . Es geht nicht unbedingt nicht darum, Nebenwirkungen zu nutzen. Wenn sich mein Programm um den Rückgabewert kümmert, verwende ich and. Wenn nicht, dann benutze ich when. IOW benutze ich when nur für Nebenwirkungen, aber ich könnte gut einen prognin einem der Argumente verwenden and. Es geht darum, ob es auf den Rückgabewert ankommt, nicht darum, ob es allein darauf ankommt.
Drew
5
andist in keiner mir bekannten Sprache eine Funktion. In Emacs Lisp ist es eine spezielle Form, in Common Lisp ist es ein Makro, einfach weil Kurzschlussverhalten erwartet wird (unmöglich mit Funktionen zu erreichen, weil sie immer ihre Argumente auswerten).
Mark Karpov
2
@lunaryorn, ja, es ist nicht wirklich relevant, aber es ist wahr, also denke ich, dass es falsch ist zu schreiben, dass andes eine Funktion ist, wenn es nicht so ist. Es ist egal, wie relevant die Tatsache für die Frage ist, wir sollten immer die richtigen Begriffe verwenden, das ist alles.
Mark Karpov
2
Nun, ich denke nicht, dass "der Wert jeder Argumentationsform wichtig ist" im Einklang mit dieser Interpretation steht. Es hätte besser ausgedrückt werden können, wenn gesagt worden wäre, dass keine Form nur bewertet wird, um ihren Wert zu verlieren.
Harald Hanche-Olsen
3
Etwas OT, aber: Der Unterschied ist mehr als stilistisch in Lisps, die nicht nil"falsch", "die leere Liste", "nichtig" usw. bedeuten. Zum Beispiel in Scheme and Racket das unwahre Ergebnis von whenist void(dh "keine Bedeutung"), wohingegen andes ist #f("falsch"). Obwohl dies für Elisp nicht zutreffend ist, könnte es ein Lisp-Generalist in Betracht ziehen.
Greg Hendershott
4

Lassen Sie mich damit beginnen (and a b)und (when a b)in Ihrem Beispiel dasselbe tun: Zuerst awird ausgewertet. bwenn ausgewertet aist wahr # .

Aber and und whenwerden für verschiedene Dinge verwendet.

  • Sie würden verwenden (and a b)zurückzukehren wahr # wenn beide aund bsind wahr # (oder Nicht-Null); und nilsonst.

  • Sie würden (when a b)oder mehr richtig sein,

    (when a
       ;; do something like b
       )

    Wenn Sie möchten, dass der Code "b" genau dann ausgeführt awird, wenn " true" # ist .


Hier ist ein Beispiel, in dem Sie whenund andzusammen verwenden:

(when (and a b)
   (do-c))

Oben, die Funktion do-cwird nur , wenn beide genannt aund bist wahr # .


Referenzen für das Studium

# Alle Verweise auf true beziehen sich auf den Booleschen Wert TRUE.

Kaushal Modi
quelle
3
andGibt nicht zurück, twenn alle Argumente nicht null sind, sondern der Wert des letzten Arguments.
Bedeutungsvoller Benutzername
1
Damit tmeine ich den Booleschen Wert WAHR oder Nicht-Null. Danke, das werde ich in meiner Antwort klarstellen.
Kaushal Modi
Ich denke, Ihre Antwort geht nicht viel weiter als das, was ich bereits in der Frage angegeben habe. Ich weiß, was beide tun, und das letzte Beispiel, das Sie geben, erscheint bereits in meiner Frage ( (when (and a b) c)). Außerdem gibt der Teil darüber, wie andund whenwie sie im Allgemeinen verwendet werden, Hinweise darauf, dass dies tatsächlich der Fall ist. Die eigentliche Grundlage für diese Frage war jedoch die Tatsache, dass ich sie häufig anders sehe (siehe zum Beispiel die Antwort, auf die ich in meiner Frage verwiesen habe).
Clément
Von einem rein funktionalen Konstrukt aus gesehen, wenn dies für nicht abschließende Auswertungen und und für direkte Symbole und Boolesche Logik gilt. Funktionale Programmierung benötigt diese Unterscheidung; Imperative Programmierung schummelt dies weg.
Emacs User
1
Ich denke nicht, dass "boolean true" klarer ist als nur "true".
YoungFrog