Dynamische/Statische Rahmen mit Deep/Shallow binding (übungen)
Ich studiere dynamische/statische Rahmen mit deep/shallow binding und ausführen von code manuell zu sehen, wie diese verschiedenen Bereiche/Bindungen tatsächlich funktionieren. Ich lese die Theorie gegoogelt und einige Beispiel-übungen und die, die ich gefunden habe sind sehr einfach (wie diese eine das war sehr hilfreich mit dynamic scoping), Aber ich habe Schwierigkeiten zu verstehen, wie statische Bereich funktioniert.
Hier poste ich eine übung, die ich Tat, um zu überprüfen, wenn ich die richtige Lösung:
unter Berücksichtigung der folgenden geschriebenes Programm in pseudocode:
int u = 42;
int v = 69;
int w = 17;
proc add( z:int )
u := v + u + z
proc bar( fun:proc )
int u := w;
fun(v)
proc foo( x:int, w:int )
int v := x;
bar(add)
main
foo(u,13)
print(u)
end;
Was gedruckt wird, auf dem Bildschirm
a) Verwendung von statischen Bereich? Antwort=180
b) mit dynamischen Umfang und Tiefe Bindung? Antwort=69 (Summe u = 126, aber es ist foo lokalen v, richtig?)
c) die Verwendung dynamischer Bereich und flacher Bindung? Antwort=69 (Summe u = 101 aber es ist foo lokalen v, richtig?)
PS: ich bin versucht, um das zu üben einige übungen wie diese, wenn Sie wissen, wo ich finden kann, diese Art von Problemen (vorzugsweise mit Lösungen) geben Sie bitte den link, danke!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihre Antwort für lexikalische (statische) Umfang korrekt ist. Ihre Antworten für dynamische Umfang falsch sind, aber wenn ich lese deine Erklärungen Recht, es ist, weil Sie verwirrt zwischen
u
undv
, statt wegen jeder echte Missverständnis darüber, wie Tiefe und flache Bindung arbeiten. (Ich gehe davon aus, dass Ihreu
/v
Verwirrung war nur Zufall und nicht durch eine seltsame Verwirrung über Werte vs. Verweise im Aufruffoo
.)Richtig.
Ihre verklärende Erklärung ist richtig, aber deine Antwort ist falsch:
u
ist in der Tat zu126
, undfoo
tatsächlich lokalisiertv
, aber damain
Druckeu
, nichtv
, die Antwort ist126
.Die Summe für
u
ist eigentlich97
(42+13+42
), aber dabar
lokalisiertu
, die Antwort ist42
. (Ihre verklärende Erklärung ist falsch, für diese ein — Sie scheinen zu haben, verwendet die Globale variablew
, die17
, in der Interpretation der Aussageint u := w
in der definition vonbar
; aber diese Aussage bezieht sich eigentlich auffoo
's lokale variablew
, seine zweite parameter, der13
. Aber das hat nicht wirklich Einfluss auf die Antwort. Deine Antwort falsch ist, nur diesen einen, weilmain
Druckeu
, nichtv
.)Zur lexikalischen Bereich, ist es ziemlich einfach, überprüfen Sie Ihre Antworten mit der übersetzung der pseudo-code in eine Sprache mit lexikalischen scope. Ebenfalls dynamischen Bereich mit einer geringen Bindung. (In der Tat, wenn Sie Perl verwenden, können Sie testen, beide Wege fast auf einmal, da es unterstützt; verwenden Sie
my
für den lexikalischen Bereich, dann eine suchen-und-ersetzen zu ändern, umlocal
für dynamische Umfang. Aber selbst wenn Sie, sagen wir, JavaScript lexikalischen Umfang und Bash für dynamische Umfang, es sollte schnell zu testen.)Dynamischen Bereich mit tiefer Bindung ist viel schwieriger, da einige weit verbreitete Sprachen unterstützen. Wenn Sie Perl verwenden, können Sie implementieren, es manuell, indem ein hash (assoziatives array), die Karten von Variablen-Namen zu Skalar-refs, und übergeben Sie diesen hash von Funktion zu Funktion. Überall, wo der pseudocode deklariert eine lokale variable, die Sie speichern Sie die vorhandenen Skalar-Referenz in Perl lexikalische variable ist, dann setzen Sie die neue Zuordnung in der hash -; und am Ende der Funktion, die Sie wiederherstellen der ursprünglichen skalaren-Referenz. Zur Unterstützung der Bindung, erstellen Sie eine wrapper-Funktion, die erstellt eine Kopie der hash und übergibt , dass seiner gewickelt Funktion. Hier ist eine dynamisch scoped -, tief-verbindliche Umsetzung des Programms in Perl, mit diesem Ansatz:
und zwar druckt er
126
. Es ist offensichtlich chaotisch und fehleranfällig, aber es hilft auch wirklich Sie verstehen, was Los ist, so für pädagogische Zwecke, ich denke, es lohnt sich!Einfache und Tiefe Bindung Lisp-interpreter, der die Gesichtspunkte der pseudocode. Scoping ist nur Zeiger-Arithmetik. Dynamischen Umfang und der statische Umfang, die gleichen sind, wenn es keine freien Variablen.
Statische Bereich setzt auf einen Zeiger auf Speicher. Leere Umgebungen halten keine symbol-Wert-Assoziationen; gekennzeichnet durch Wort "Ende". Jedes mal, wenn der interpreter liest eine Zuordnung, es lässt Raum für Assoziation zwischen einem symbol und Wert.
Umwelt-Zeiger wird aktualisiert, und zeigen Sie den letzten Verband angelegt.
Lassen Sie mich notieren Sie sich diese Umgebung Speicherplatz AAA. In meinem Lisp-interpreter, bei einem treffen ein Verfahren, nehmen wir die Umwelt-pointer und setzen es unsere Tasche.
Das ist so ziemlich alles da ist, bis das Verfahren
add
genannt wird. Interessanterweise, wennadd
nie aufgerufen wird, Sie nur Kosten selbst ein Zeiger.Nehme an, ruft das Programm
add(8)
. OK, let ' s roll. Die Umgebung AAA ist der aktuelle. Umwelt ist->[w,17]->[v,69]->[u,42]->End
.Verfahren Parameter
add
werden Hinzugefügt, um die front der Umgebung. Die Umwelt wird[z,8]->[w,17]->[v,69]->[u,42]->End
.Nun das Verfahren Körper
add
ausgeführt wird. Freie variablev
wird Wert 69. Freie variableu
wird Wert 42.z
wird der Wert 8.u
zugewiesen wird der Wert von 69 + 42 + 8 becomeing 119.Die Umgebung wird dies widerspiegeln:
[z,8]->[w,17]->[v,69]->[u,119]->End
.Davon ausgehen Verfahren
add
hat seine Aufgabe erfüllt. Nun ist die Umgebung wird wieder auf den vorherigen Wert.Bemerken, wie das Verfahren
add
hatte eine Nebenwirkung der änderung der Wert der freien Variablenu
. Genial!Zu dynamic scoping: es sorgt für die Schließung Blätter, dynamische Symbole, wodurch er gefangen genommen und immer dynamisch.
Dann legte Zuordnung dynamischer oben im code. Wenn dynamische identisch ist, die parameter name, es wird maskiert durch den parameter-Wert übergeben.
Angenommen, hatte ich eine dynamische variable namens
z
. Als ichadd(8)
,z
gewesen wäre, eingestellt zu 8 unabhängig davon, was ich wollte. Das ist wahrscheinlich der Grund, warum dynamischen Variablen haben längere Namen.Gerücht hat es, dass die dynamischen Variablen sind nützlich für Dinge wie backtracking, mit let ' Lisp-Konstrukte.
Statische Bindung, auch bekannt als lexikalischen Umfang, bezieht sich auf den scoping-Mechanismus gefunden in den meisten modernen Sprachen.
In der "lexical scope", der Letzte Wert für u ist weder 180 oder 119, die falschen Antworten.
Die richtige Antwort ist u=101.
Finden Sie standard-Perl-code unten, um zu verstehen, warum.
Bezüglich flache Bindung versus Tiefe Bindung, beide Instrumente stammen aus der ehemaligen LISP-ära.
Beide Mechanismen sind bedeutete, zu erreichen, dynamische Bindung (versus lexikalischen Umfang Bindung) und daher Sie produzieren identische Ergebnisse !
Die Unterschiede zwischen flache Bindung und Tiefe Bindung, die Ihren Wohnsitz nicht in der Semantik, die identisch sind, aber in der Umsetzung dynamische Bindung.
Mit Tiefe Bindung, Variablen-Bindungen liegen in einem Stapel als "varname =" > "varvalue" Paare.
Finden Sie den code unten ein Perl-Implementierung von deep-binding dynamischen Umfang.
Das Ergebnis ist u=97
Dennoch, diese ständige Durchlaufen der Bindung stack ist teuer : 0(n) Komplexität !
Flache Bindung bringt eine wunderbare O(1) verbesserte Leistung gegenüber dem bisherigen Umsetzung !
Flache Bindung ist die Verbesserung der ehemaligen Mechanismus durch die Zuordnung jeder variable eine eigene "Zelle", die Speicherung wird der Wert der Variablen innerhalb der Zelle.
Zelle (unter Verwendung einer hash-Tabelle auf Variablennamen, erreichen wir eine
0(1) Komplexität für den Zugriff auf Variablen!)
variable Zelle.
der Variablen (eine Vorherige Bindung) auf den stack und die Speicherung der
neue lokale Wert in der Zelle "Wert".
aus dem stack in die variable, die den Wert der Zelle.
Lesen Sie bitte den folgenden code für eine einfache Perl-Implementierung von shallow-binding dynamischen Umfang.
Wie Sie sehen werden, das Ergebnis ist immer noch u=97
Als Fazit, erinnere mich an zwei Dinge :
flache Bindung liefert die gleichen Ergebnisse wie Tiefe Bindung, läuft aber schneller, da es nie eine Notwendigkeit, um die Suche für eine Bindung.
Das problem ist nicht flache Bindung versus Tiefe Bindung versus
statische Bindung ABER lexikalischen Umfang versus dynamischen Umfang (realisiert entweder mit deep-oder shallow-binding).