2011-10-27 11 views
12

Si evaluamos estas líneas uno a uno, se creará x en el contexto cc.¿Por qué este uso de Begin [] no funciona?

Begin["cc`"]; 
x = 1; 
End[] 

Sin embargo, si los evaluamos juntos,

(Begin["cc`"]; 
x = 1; 
End[]) 

continuación x se creará en Global. Esto es a pesar de la siguiente impresión cc`:

(Begin["cc`"]; 
Print[$Context]; 
End[]) 

¿Cuál es la razón de este comportamiento? Supongo que los contextos solo importan durante la fase de análisis, no de evaluación.

Caso de uso: Quería crear una paleta Button que definirá algunos símbolos si aún no existen, en un contexto "privado" para evitar conflictos con los globales. ¿Cuál es el método preferido para hacer esto, aparte de poner todas las definiciones en un archivo de paquete y cargarlas desde la paleta? (Me gustaría mantener la paleta autónoma.)

+0

acabo de leer en documentos que eso "La interpretación de los nombres de los símbolos depende del contexto' Begin' por lo tanto afecta el análisis de las expresiones de entrada." Eso responde mi primera pregunta. El segundo sigue en pie. – Szabolcs

Respuesta

15

Los símbolos (y sus contextos) se crean al analizar, no a la evaluación. Si utilizamos $NewSymbol podemos ver esto en efecto:

$NewSymbol=Print["Name: ",#1," Context: ",#2]&; 

Print["first"]; 
test1; 
Print["last"] 

(Print["first"]; 
test2; 
Print["last"]) 

Los primeros uno grabados:

first 
Name: test1 Context: Global` 
last 

porque cada línea en la célula es tratada como una entrada separada. El segundo utiliza paréntesis para forzar las tres líneas que han de considerarse una entrada y grabados

Name: test2 Context: Global` 
first 
last 

de la que podemos ver que test2 fue creado en el contexto Global` antes de que ocurriera cualquier evaluación.

Creo que la manera más fácil de trabajar con esto es utilizar un contexto explícito en su símbolo: cc`x = 1.

+0

+1, resultado interesante. – rcollyer

+3

Otra opción que a veces es útil es usar ToExpression para hacer un nuevo análisis * durante la evaluación *: (Begin ["cc'"]; With [{s = ToExpression ["x"]}, s = 1]; End [ ];) –

+0

Brett, ¿hay alguna forma de usar '$ NewSymbol' para forzar que un símbolo se cree en un contexto específico y, por extensión, no en el predeterminado? –

2

Para su segunda pregunta, lo remito a this respuesta mía, que efectivamente automatiza los pasos que se describen (con la función ParseTimeNameSpaceWrapper). Es posible que necesite más trabajo para hacerlo más robusto, pero ese podría ser un punto de partida. Yo uso esto yo mismo en alguna ocasión.

+0

'ParseTimeNameSpaceWrapper' todavía no evita el hecho de que el contexto de los símbolos se decide en tiempo de análisis, es decir, si hago' ParseTimeNameSpaceWrapper [x] ', esa' x' todavía se interpretará como '' Global'x' ', no como' 'MyLocalizedContext'x''. Después de entender que el contexto se elige en tiempo de análisis, creo que no hay otra manera más que forzar un nuevo análisis ya sea poniendo un código en una cadena y usando 'ToExpression', o leyéndolo desde un paquete (o simplemente escribiendo el contextos explícitamente como sugiere Brett, pero eso es mucho trabajo para un código más largo). – Szabolcs

+0

@Szabolcs veo. Tal vez este hilo sea de su interés en relación con la etapa de análisis: http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/c1f4ab24db8a8542 –

0

Sólo como referencia:

(Begin["cc`"]; Evaluate[Symbol["x"]] = 1; End[]) 

cc`x 
1 
Cuestiones relacionadas