2010-04-29 7 views
7

Wie in einer aktuellen post hingewiesen wurde, funktioniert das Scoping innerhalb des Moduls nicht wie erwartet.Warum würde Mathematica die normalen Scoping-Regeln in Module brechen?

Ein Beispiel aus diesem Thread ist:

Module[{expr}, 
expr = 2 z; 
    f[z_] = expr; 
    f[7]] 
(*2 z*) 

Aber die folgende funktioniert fast wie erwartet.

Module[{expr}, 
expr = 2 z; 
    [email protected]@{f[z_], expr}; 
    f[7]] 
(*14*) 

Welchen Sprachentwurf berücksichtigte Wolfram, um diese Funktionalität zu wählen?

Edit: Siehe Jefromi ersten Kommentar Ich änderte z von einer lokalen Variable zu nicht und vergaß, die Ausgabe zu ändern. Es wirkt sich nicht auf das Problem aus.

Edit2: Michael Pilats Punkt scheint zu sein, dass Block und Modul unterschiedliche Funktionen haben. Ich denke, ich verstehe seinen Standpunkt, aber ich denke, dass es zu meiner Frage orthogonal ist. Also hier ist ein Update.

kann ich den folgenden Code an dem der globalen Ebene in einem Notebook verwenden:

expr = 2 z; 
f[z_] = expr; 
f[7] 
(*output: 14*) 

Aber wenn ich den gleichen Code-Block in ein Modul setzen und ausdr lokalen mache es erzeugt einen anderen Ausgang.

Clear[f]; 
Module[{expr}, 
expr = 2 z; 
f[z_] = expr; 
f[7]] 
(*output: 2z*) 

Wenn Sie die oben Modul Trace rufen Sie feststellen, dass Set [f [z_], ausdr] wird [f [z $ _, ausdr] auf neu geschrieben. Nun passiert diese Transformation z-> z $ sowohl auf der linken als auch auf der rechten Seite der Menge. Es passiert jedoch, bevor expr ausgewertet wird, was zu einem anderen Ergebnis führt als auf globaler Ebene.

Die Transformation z-> z $ scheint nur dann zu passieren, wenn die rhs ein lokales Symbol für den Modulaufruf hat.

Warum wählt Mathematica diese Syntaxänderung in einem Modulaufruf? Welche Kompromisse zwischen Sprache und Implementierung gibt es hier, die diese Entscheidung getroffen haben.

+0

Welche Version von Mathematica verwenden Sie? Liefert das erste wirklich das lokale z ('z $ 1776') des Moduls statt nur' 2z' (was ich mit der Version 6.0.0 bekomme). – Cascabel

+0

Oder ist das lokale z, das vom Muster erstellt wird, identisch? – Cascabel

+1

Von Trace scheint es, dass Mathematica entscheidet, dass, weil es eine lokale Variable auf der RHS der Menge gibt, eine lokale Variable für das Muster verwendet wird ('f [z $ _] = expr $ 64'). In allen anderen Fällen kann ich mir vorstellen, dass wenn das RHS keine lokale Variable enthält, es das erwartete 'f [z_] = ...' verwendet. Vielleicht gibt es einen vernünftigen Fall von Evaluation, in dem dieses Verhalten Sinn macht, aber ich kann es mir nicht vorstellen. +1, und ich hoffe, dass jemand es schafft, zu antworten. – Cascabel

Antwort

2

Nach the documentation hat ModuleHoldAll Attribut, das alles innerhalb der Module verursacht in einem unevaluierten Zustand zu bleiben, so wird Ihre expr nicht zu 2 z ausgewertet, bevor expr wird f[z_] zugeordnet.

das zweite Argument in Evaluate-Module Wrapping scheint das Problem zu lösen:

In[1]:= Module[{expr}, Evaluate[expr = 2 z; 
    f[z_] = expr; 
    f[7]]] 

Out[1]= 14 

Auch Block statt Module Arbeiten mit:

In[2]:= Block[{expr = 2 z}, 
f[z_] = expr; 
f[7]] 

Out[2]= 14 
+0

Indem Sie Evaluate verwenden, obwohl Sie expr eine globale Variable statt einer lokalen Variable erstellt haben. – Davorak

5

ich die Antwort denken, ist ziemlich einfach, aber subtil: Module ist ein lexikalisches Scoping-Konstrukt, und Block ist ein dynamisches Scoping-Konstrukt.

Die Blocks Compared With Modules Tutorial aus der Dokumentation beschreibt die Unterscheidung:

Wenn lexikalischen Scoping verwendet wird, werden Variablen als lokal für einen bestimmten Abschnitt des Codes in einem Programm behandelt.Beim dynamischen Scoping sind die Werte von Variablen lokal für einen Teil des Ausführungsverlaufs des Programms. In kompilierten Sprachen wie C und Java wird sehr klar zwischen "Code" und "Ausführungshistorie" unterschieden. Die symbolische Natur von Mathematica macht diese Unterscheidung etwas weniger klar, da "Code" im Prinzip dynamisch während der Ausführung eines Programms aufgebaut werden kann.

Was Module[vars, body] tut, ist die Form des Ausdruckskörpers zu dem Zeitpunkt behandeln, wenn das Modul als "Code" eines Mathematica-Programms ausgeführt wird. Wenn dann einer der Variablen explizit in diesem "Code" erscheint, wird er als lokal betrachtet. Block[vars, body] schaut nicht auf die Form des Ausdrucks body. Stattdessen verwendet der Block bei der Auswertung von body lokale Werte für die Variablen.

Es bietet dieses reduzierte Beispiel:

In[1]:= m = i^2 

Out[1]= i^2 

(* The local value for i in the block is used throughout the evaluation of i+m. *) 
In[2]:= Block[{i = a}, i + m] 

Out[2]= a + a^2 

(* Here only the i that appears explicitly in i+m is treated as a local variable. *) 
In[3]:= Module[{i = a}, i + m] 

Out[3]= a + i^2 

Vielleicht ist der entscheidende Punkt ist, zu erkennen, dass Module alle Instanzen i in dem Modulkörper mit einer lokalisierten Version ersetzt (zB i$1234) lexikalisch, vor jeder der Körper des Moduls wird tatsächlich ausgewertet.

Daher ist der Modulkörper, der tatsächlich ausgewertet wird, i$1234 + m, dann i$1234 + i^2, dann a + i^2.

Nichts ist kaputt, Block und Module sollen sich anders verhalten.

+0

Das ist nahe an dem, was ich in der letzten Frage beantwortet habe. Der Punkt der lexikalischen Festlegung von etwas ist so, dass man einige Variablen lokal machen kann und alles andere unverändert lässt. Modul lässt alles andere nicht unverändert. Wie dient das Ändern der verfügbaren Syntax dem Zweck des Moduls? Betrachten Sie die Trace der Module über einem mit f [z _] = expr und eins mit f [z_] = . Der erste hat z als z $ umgeschrieben und im späteren z bleibt er unverändert. Warum interagiert das Modul auf diese Weise mit zusätzlichen internen Scopings? Gibt es einige Kriterien für das Sprachdesign, die ich vermisse? – Davorak

+0

Wenn Modul im letzten Fall z nicht als z $ geschrieben hat, dann hätte die Menge von f [z_] funktioniert, da sie außerhalb einer Modulanweisung hätte und wie sie funktionieren würde. Auch danke. – Davorak

+0

Nur für den Fall, dass es nicht klar war, verstehe ich nicht, wie Sie das Beispiel auf das Beispiel anwenden sollten, das ich zur Verfügung gestellt habe, da alle Sets in meinem Beispiel in der Modul-Anweisung vorkommen und Ihre nicht. – Davorak

Verwandte Themen