JMP-Bereich – Dynamischer vs. lexikalischer Bereich und allgemeine Verwirrung beim Lernen von JSLWenn ich falsch liege, korrigieren Sie mich bitte, aber es scheint, dass JMP einen dynamischen Bereich ohne Bereichspersistenz hat (mit Ausnahme der Pseudo-Namespaces). Hier , Fenster , Kasten ).Dies steht im Gegensatz zu vielen gängigen Programmiersprachen, die über einen lexikalischen Gültigkeitsbereich mit vollständiger Gültigkeitsbereichspersistenz unter Verwendung von Referenzzählern verfügen.
Das löste bei mir eine Menge Kopfzerbrechen aus, bis ich die nötige Intuition erlangte, um mit dem seltsamen Scope-System von JMP zu arbeiten, und ich glaube, dass es bei vielen Menschen für große Verwirrung sorgt.Nicht viele Programmiersprachen verwenden den dynamischen Bereich (LISP ist eine wichtige Ausnahme, und JSL weist einige Ähnlichkeiten mit LISP auf).
Ich möchte das JSL-Dokumentationsteam ermutigen, auf diesen Unterschied hinzuweisen und einige Ressourcen/Links zum besseren Verständnis des dynamischen Bereichs bereitzustellen, da dies sicherlich nicht die Standardmethode zur Namensauflösung ist.
Hier ist ein Beispiel: Der lokale Gültigkeitsbereich der äußeren Funktion wird unmittelbar nach der Return-Anweisung gelöscht, und die Namensauflösung der inneren Funktion erfolgt dynamisch (basierend auf dem aktuellen Aufrufstapel):
Names Default to Here( 1 );
x = 7;
outer function = Function( {},
{x},
x = 4;
inner function = Function( {},
Print( x )
);
Return( Name Expr( inner function ) );
);
func = outer function;
func()
/*** OUTPUT ***
7Wenn Sie in einer Sprache mit lexikalischem Geltungsbereich und Bereichspersistenz (wie Python) etwas funktional Äquivalentes tun, dann ist der umschließende Bereich der inneren Funktion persistent (es ist der lokale Bereich für die äußere Funktion) und die Namensauflösung für die innere Funktion Die x-Variable der Funktion ist der Wert 4 aus der lexikalischen Lesart des Systems.Da JMP keinen lexikalischen Bereich, sondern einen dynamischen Bereich verwendet, verwendet es, wenn die innere Funktion schließlich am Ende des Skripts ausgeführt wird, die dynamische Namensauflösung „Lokal -> Hier -> Global“ (und mögliche Spalten-) Namen für die aktuelle Tabelle) und findet den Wert 7.
Das Verständnis dieser Art von Verhalten ist für die Erstellung robuster Programme in JSL von entscheidender Bedeutung, und ich möchte nur jeden darauf hinweisen, der mit JSL lernt oder Probleme damit hat.
Lassen Sie mich wissen, wenn Sie irgendwelche Gedanken oder nicht intuitive Beispiele haben!
Automatisierung und SkripterstellungDatenzugriffBetreff: JMP-Geltungsbereich – Dynamischer vs. lexikalischer Geltungsbereich und allgemeine Verwirrung beim Lernen von JSLDas ist wahr und hat mich beim Erlernen der Sprache definitiv aus der Fassung gebracht.Die andere Falte ist, dass JSL ein ist Begriffsumschreibungssprache dank seiner Ausdrucksobjekte, was bedeutet, dass es zwar in Bezug auf den Umfang LISP-artig ist, in Bezug auf die Art und Weise, wie es mit Makros umgeht, jedoch nicht LISP-artig ist.
Die einzige andere Sprache zum Umschreiben von Begriffen, die mir bekannt ist und häufig verwendet wird, ist Wolfram Language.Ich kenne mich in CS nicht gut genug aus, um das mit Sicherheit sagen zu können, aber ich habe einige Leute behaupten hören, dass das Paradigma der Begriffsumschreibung grundsätzlich leistungsfähiger ist als die Makros von Lisp.Andererseits habe ich einige Behauptungen gehört, dass Wolfram Language lediglich eine Implementierung von M-Ausdrücken sei, wobei Lisp entschied, dass S-Ausdrücke gut genug seien.
Unabhängig davon wird das Ausdruckssystem von JSL nahezu jedem fremd sein, und die Ergonomie ihrer Funktionen für die Arbeit mit Ausdrücken tut ihnen keinen Gefallen.Es gibt einen Grund dafür, dass Sie in diesem Forum so viele Beispiele von Leuten finden, die String-Manipulation und Parse() anstelle der Funktionen zum Umschreiben von Begriffen verwenden.
Betreff: JMP-Geltungsbereich – Dynamischer vs. lexikalischer Geltungsbereich und allgemeine Verwirrung beim Lernen von JSLIch selbst bin kein CS-Mensch, aber dieser Kram zum Umschreiben von Semestern ist ziemlich interessant!Danke für den Hinweis, ich werde jetzt die ganze Nacht in diesem Kaninchenbau verbringen ...
Betreff: JMP-Gültigkeitsbereich – Dynamischer vs. lexikalischer Gültigkeitsbereich und allgemeine Verwirrung beim Erlernen von JSLDer
func = outer function;
func();
hat mich verwirrt.
Nach der Ausführung
func = outer function();
Die Definition der inneren Funktion wird in der Variablen func gespeichert.
Deshalb gibt Show(func) Folgendes zurück
func = Function({},Print(x));
An diesem Punkt sind alle Informationen über die äußere und die innere Funktion verloren gegangen.
Die Funktion func() führt also Print(x) aus und gibt 7 aus.
bearbeiten:
Tatsächlich gibt es nichts Neues im Vergleich zu dem, was im Hauptbeitrag geschrieben wurde.
Lediglich die „2D-Sichtweise“ eines JSL-Programmierers.
Betreff: JMP-Gültigkeitsbereich – Dynamischer vs. lexikalischer Gültigkeitsbereich und allgemeine Verwirrung beim Erlernen von JSLJMP behält die Variablen in der Funktionsdefinition so bei, wie sie sind – es ersetzt sie nicht automatisch durch den aktuellen Wert.
Also, nachdem
x = 4;
inner function = Function( {}, Print( x ));
inner function is defined as
Function( {}, Print( x ));
Damit die innere Funktion ihr x durch das x der äußeren Funktion ersetzt, benötigt man eine Vorberechnung wie zum Beispiel
Names Default to Here( 1 );
x = 7;
outer function = Function( {},
{x},
x = 4;
Eval(Eval Expr( inner function = Function( {},
x= Expr(x);
Print( x )
)));
Return( Name Expr(inner function));
);
func = outer function;
func() // prints 4
Bearbeitung: Dieselbe 2D-Ansicht mit anderen Wörtern.
Betreff: JMP-Gültigkeitsbereich – Dynamischer vs. lexikalischer Gültigkeitsbereich und allgemeine Verwirrung beim Erlernen von JSLIch warf einen kurzen Blick über den Zaun:
def outer():
y=4
def inner():
print(y)
return inner
f = outer()
y = 7
f() # -> 4
Python gibt also 3 zurück. Denn so ist y im lexikalischen Kontext definiert, wenn inner definiert ist.
„Definiert“ oder „zurückgegeben“?
Schauen wir uns das noch einmal an:
def outer():
y=4
def inner():
print(y)
y=-100
return inner
f = outer()
y = 7
f()
-> -100