Die Sprache, die ich lerne, ist Schema und ich arbeite an einer Übung, die Folgendes gibt:
(define (p) (p) )
(define (test x y) (if (= x 0)
0
y))
Dann wird die Frage gestellt, den Ausdruck zu bewerten: (Test 0 (p)) und das Verhalten zu kommentieren, das bei der Bewertung der normalen Reihenfolge und der anwendbaren Reihenfolge beobachtet werden würde.
Das sind meine Gedanken:
Bei normaler Reihenfolge wertet das Programm die Unterausdrücke aus, bevor es fortfährt:
So ( test 0 (p) )
wird:
(test 0 p)
( if (= x 0) 0 p))
Ausgabe zurückgeben 0
Der einzige Unterschied in der Anwendungsreihenfolge besteht darin, dass das Programm wie folgt ausgeführt wird:
( test 0 (p) )
wird:
(test 0 (p))
( if (= x 0) 0 (p)))
Ausgabe zurückgeben 0
Somit (p)
würde niemals ausgewertet, da es nicht benötigt wird.
Ist das richtig? Bitte lassen Sie es mich wissen, da ich fast keine Programmiererfahrung habe.
Antworten:
Welche Nachforschungen haben Sie angestellt, um diese Frage zu beantworten? Ich habe es einfach so eingesteckt, wie es in Google ist, und als zweite Antwort (die erste ist vielleicht so gut, ich habe sie nicht überprüft) einen Verweis auf einen Abschnitt einer Bibel zu Ihrem Thema erhalten: Hal Abelsons, Jerry Sussmans und Julie Sussmans Struktur und Interpretation von Computerprogrammen (MIT Press, 1984; ISBN 0-262-01077-1), auch bekannt als das Assistentenbuch. Der Verweis bezieht sich auf den Abschnitt " Normale Bestellung und anwendbare Bestellung ".
Es sagt aus:
und fügt hinzu, dass letzteres als faule Bewertung bezeichnet wird .
Sie haben also falsche Definitionen und nehmen eine für die andere:
Die anwendbare Reihenfolge wertet Unterausdrücke aus, wenn, dh kurz bevor das Verfahren angewendet wird.
Die normale Reihenfolge übergibt die Unterausdrücke unverändert ohne Auswertung und fährt mit der Auswertung nur fort, wenn der entsprechende formale Parameter tatsächlich selbst ausgewertet werden soll. (Es gibt eine weitere Wendung in Bezug auf Umweltprobleme ... aber das vergessen wir an dieser Stelle besser).
Darüber hinaus verstehen Sie den Anrufmechanismus, der zwei Dinge umfasst, nicht richtig:
den Parameterübergabemechanismus, der die ordnungsgemäße Verarbeitung der tatsächlichen Argumente für den Aufruf in Abhängigkeit von der Bewertungsregel umfasst;
das "Ersetzen" des Aufrufs der Funktion durch den Hauptteil der Funktion (ohne den Header).
Bei der Bewertung der anwendbaren Reihenfolge von
( test 0 (p) )
sollten Sie zuerst die Argumentausdrücke auswerten. Das sind0
und(p)
.Die Bewertung eines wörtlichen Wertes
0
ergibt diesen Wert.Das zweite Argument ist jedoch ein Prozeduraufruf für eine aufgerufene Prozedur ohne Parameter
p
. Es hat keinen Parameter, so dass wir uns keine Sorgen um die Auswertungsreihenfolge machen müssen. Um die Bewertung fortzusetzen, müssen wir dann den Aufruf durch den Hauptteil der Prozedur ersetzen, die der Liste der Argumente folgt, und dann diesen Hauptteil bewerten. Das inp
der Erklärung festgelegte Verfahren(define (p) (p) )
ist(p)
so, dass wir die Bewertung dessen behalten, was wir gerade zu bewerten versuchten. Mit anderen Worten, der Bewertungsprozess befindet sich in einer Schleife und wird nicht beendet.... und Sie können den Aufruf der Funktion nie tatsächlich beenden
test
, da die Auswertung ihrer Argumente nicht beendet wird. Ihr Programm wird nicht beendet.Dieses Risiko der Nichtbeendigung, selbst wenn das Schuldargument niemals im Aufruf verwendet wird, ist einer der Gründe für die Verwendung einer normalen Auftragsbewertung, die möglicherweise etwas schwieriger zu implementieren ist, aber möglicherweise bessere Beendeneigenschaften aufweist.
Bei der normalen Ordnungsbewertung berühren Sie die Argumentunterausdrücke nicht. Was Sie tun, ist, den Aufruf
( test 0 (p) )
durch den Hauptteil der Funktion zu ersetzentest
, dh(if (= x 0) 0 y)
wo die Namen der (formalen) Argumentex
undy
durch die entsprechenden tatsächlichen Argumente ersetzt werden0
und(p)
(bis zur Umgebung oder Umbenennungsprobleme, die wichtig sind, aber die komplizieren würden Erklärung hier und sind der Hauptunterschied zwischen der ursprünglichen Lisp- und der Schemasprache).Daher ersetzen Sie die Bewertung von
( test 0 (p) )
durch die Bewertung von(if (= 0 0) 0 (p))
.Jetzt ist die Funktion
if
eine primitive Funktion, die normalerweise immer ihr erstes Argument auswertet, aber ihre letzten beiden Argumente in normaler Reihenfolge auswertet und nur das nützliche auswertet, je nachdem, ob das erste als falsch oder wahr (tatsächlichNIL
oder#f
für falsch oder ein anderes) ausgewertet wird Wert für wahr , im Fall von Schema - wenn mein Gedächtnis mich nicht verfehlt). Da sich die(= 0 0)
Bewertung als wahr herausstellt, wird die Bewertung des bedingten Betrags zur Bewertung des noch nicht bewerteten zweiten Arguments durchgeführt, was0
(außer im alten Fortran) nicht überraschend ist0
.Tiefer Atemzug.
quelle