2013-10-27 7 views
5

ich in einem großen Dilemma bin, nehmen Sie den folgenden Code in ML geschrieben:Lexical Scope in Python vs ML

val x = 1 
fun f(y) = x + y 
val x = 2 
val y = 3 
val z = f (x + y) 

Der Wert von z 6. Nun ist, wenn ich den gleichen Code in Python den Wert schreiben von z wäre 7. Und beide Sprachen behaupten (die Lehrer, die diese Sprachen lehren, behaupten dies), einen lexikalischen/statischen Geltungsbereich zu haben. Aber es sieht aus wie nur ML es hat, indem es die Umgebung verwendet, die erstellt wurde, als die f-Funktion definiert wurde, wann immer f heißt

Alle Zeiger würden sehr geschätzt werden!

Danke!

Antwort

6

In Python sind Schließungen durch Variable, nicht durch Wert. Wenn Sie also in einer Funktion auf x verweisen, bezieht sich das auf den letzten Wert, der x zugewiesen wurde, nicht auf den Wert x, als die Funktion definiert wurde. Dies wird nicht-intuitive Ergebnisse wie die unten:

adders = [] 
for x in range(10): 
    adders.append(lambda y: x+y) 

Sie beabsichtigen, eine Liste von Funktionen zu machen, die x auf einen Wert hinzufügen, wo x von 0 variiert ... 9, sondern sie alle in 9, weil das ist der Wert von x am Ende der Schleife.

Sie können dies überschreiben, indem Sie ein Standardargument verwenden, um den Namen zum Zeitpunkt der Funktionsdefinition an seinen Wert zu binden.

x = 1 
f = lambda y, x=x: x + y # x inside f is now locked at 1 
x = 2 
y = 3 
z = f(x + y) 

In diesem Beispiel sind Sie nicht einmal tatsächlich mit einem Verschluss zu tun: x hier ist eigentlich eine globale Variable. In Python kann eine Closure nur dann erstellt werden, wenn eine Funktion in einer anderen Funktion definiert ist und der globale Namespace auf oberster Ebene oder Modul keine Funktion ist. Aber es gilt das gleiche Prinzip: Die globale Variable kann natürlich geändert werden, nachdem die Funktion definiert wurde. Wenn Sie also ihren Wert zum Zeitpunkt der Funktionsdefinition "sperren" wollen, verwenden Sie ein Standardargument.

+0

Nun, Sie könnten auch sagen, dass in ML Variablen auch durch Referenz erfasst werden - Variablen können nicht in ML zugewiesen werden, also ob Variablen durch Wert oder durch Referenz erfasst werden, macht keinen Unterschied. – newacct

+0

Ja, ich weiß nicht genug über ML, um etwas darüber zu sagen. :-) – kindall

6

In ML - zumindest im funktionalen Teil von ML - gibt es keine Variablenzuordnung. Sobald Sie das val x = 1 deklariert haben, können Sie den Wert x nicht ändern.

Was Sie können tun, ist jedoch eine andere x erklären. Wenn Sie val x = 2 sagen, führen Sie eine brandneue Variable namens x ein, die im Grunde nur die alte versteckt. Aber die Funktion f wurde bereits definiert, um auf das Original x zu zeigen, so dass es nicht betroffen ist.

ML unterstützt mutable types, die wie Variablen in Python neu zugewiesen werden können. Aber sie sind so weit von dem funktionalen Paradigma entfernt, dass Sie kaum einen Grund haben sollten, sie zu benutzen. Wenn Sie so programmieren wollen, ist Python eine viel bessere Sprache dafür.

+1

Es gibt keine Variablenzuweisung in ML, Punkt. (Es gibt einfach nicht einmal eine Syntax für die Zuweisung zu einer Variablen.) Sie können Referenzen auf veränderbare Datenstrukturen haben, und Sie können diese Datenstruktur ändern. Sie können sie jedoch keiner Variablen zuweisen. – newacct