2010-04-29 8 views
7

Como se señaló en un reciente post, el alcance no funciona como se esperaba dentro del Módulo.¿Por qué Mathematica rompería las reglas normales de alcance en el Módulo?

Un ejemplo de ese hilo es:

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

Pero el siguiente funciona casi como se esperaba.

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

¿Qué consideración de diseño de lenguaje se toma con wolfram esta funcionalidad?

Editar: Ver el comentario de Jefromi. Cambié z de ser una variable local a no y olvidé cambiar la salida. No afecta el problema

Edit2: El punto de Michael Pilat parece ser que el Bloque y el Módulo tienen diferentes funciones. Creo que entiendo su punto, pero creo que es ortogonal a mi pregunta. Así que aquí hay una actualización.

que puede utilizar el código siguiente en el nivel global en un cuaderno:

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

Pero cuando pongo el mismo bloque de código en un módulo y hacer llamadas locales expr que produce una salida diferente.

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

Si se desplaza por el módulo anterior llame encuentran que Set [f [z_], expr] se reescribe para establecer [f [z $ _, expr]. Ahora esta transformación z-> z $ ocurre tanto en lhs como en rhs del conjunto. Sin embargo, sucede antes de que se evalúe expr, lo que provoca un resultado diferente que luego se obtendría a nivel global.

La transformación z-> z $ parece ocurrir cuando el rhs tiene un símbolo local para la llamada al Módulo.

¿Por qué Mathematica elige tener este cambio de sintaxis en una llamada al Módulo? ¿Qué combinaciones de lenguaje/diseño de implementación existen aquí que tomaron esta decisión?

+0

¿Qué versión de mathematica estás usando? ¿El primero realmente te da la z local del módulo ('z $ 1776') en lugar de solo' 2z' (que es lo que obtengo, usando la versión 6.0.0). – Cascabel

+0

¿O es que la z local creada por el patrón coincide? – Cascabel

+1

De Trace, parece que Mathematica decide que debido a que hay una variable local en el RHS del conjunto, usará una variable local para el patrón ('f [z $ _] = expr $ 64'). En todos los demás casos que puedo pensar, cuando el RHS no contiene una variable local, utiliza el 'f [z_] = ...' esperado. Tal vez haya algún caso razonable de evaluación en el que este comportamiento tenga sentido, pero ciertamente no puedo pensar en ello. +1, y espero que alguien logre responder. – Cascabel

Respuesta

2

Según the documentation, Module tiene atribuir HoldAll, lo que hace que todo dentro de la Module a permanecer en un estado sin evaluar, por lo que su expr no se evalúa a 2 z antes expr se asigna a f[z_].

Envolver el segundo argumento de Module en Evaluate parece resolver el problema:

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

Out[1]= 14 

Además, el uso Block en lugar de Module obras:

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

Out[2]= 14 
+0

Al usar Evaluar sin embargo ha hecho de expr una variable global en lugar de una local. – Davorak

5

Creo que la respuesta es bastante simple, pero sutil: Module es una construcción de alcance léxico, y Block es una construcción de ámbito dinámico.

El Blocks Compared With Modules tutorial de la documentación discute la distinción:

Cuando se usa ámbito léxico, las variables son tratadas como local para una sección particular del código en un programa.En el ámbito dinámico, los valores de las variables son locales en una parte del historial de ejecución del programa. En lenguajes compilados como C y Java, hay una distinción muy clara entre "código" e "historial de ejecución". La naturaleza simbólica de Mathematica hace que esta distinción sea menos clara, ya que el "código" puede, en principio, acumularse dinámicamente durante la ejecución de un programa.

Lo que Module[vars, body] hace es tratar la forma del cuerpo de la expresión en el momento en que el módulo se ejecuta como el "código" de un programa de Mathematica. Entonces, cuando cualquiera de los vars aparece explícitamente en este "código", se considera que es local. Block[vars, body] no mira la forma del cuerpo de la expresión. En cambio, a lo largo de la evaluación del cuerpo, el bloque usa valores locales para los vars.

Ofrece esta reducida ejemplo:

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 

Tal vez el punto clave es darse cuenta de que Module reemplaza todas las instancias de i en el cuerpo del módulo con una versión localizada (por ejemplo, i$1234) léxico, antes de cualquiera del cuerpo del módulo se evalúa realmente. Por lo tanto, el cuerpo del módulo que se evalúa realmente es i$1234 + m, luego i$1234 + i^2, luego a + i^2.

Nada se rompe, y BlockModule están destinadas a comportarse de manera diferente.

+0

Eso está cerca de lo que respondí en la última pregunta. El objetivo de determinar algo de forma léxica es que puedas hacer que algunas variables sean locales y que todo lo demás permanezca inalterado. El módulo no deja todo lo demás sin cambios. ¿Cómo funciona el cambio de la sintaxis disponible para el propósito del Módulo? Mire el Trace of the Modules encima de uno con f [z _] = expr y uno con f [z_] = . El primero ha sido z reescrito como z $ y en la última z permanece sin cambios. ¿Por qué el Módulo interactúa con el alcance interno adicional de esta manera? ¿Hay algún criterio de diseño del lenguaje que me falta? – Davorak

+0

Si el Módulo no reescribió z como z $ en el caso posterior, entonces el Conjunto de f [z_] habría funcionado como lo hubiera hecho al margen de una declaración del módulo y cómo se esperaría que funcionara. También gracias. – Davorak

+0

En caso de que no esté claro, no entiendo cómo se supone que su ejemplo se aplica al ejemplo que proporcioné, ya que todos los Conjuntos en mi ejemplo aparecen en la declaración del Módulo y el suyo no. – Davorak

Cuestiones relacionadas