2010-11-24 16 views
7

De vez en cuando me encuentro con el siguiente escenario - un procedimiento utiliza una función global f[x] hacer algún cálculo, por su parte otro procedimiento hace f=5 que convierte todas las llamadas posteriores f[x] en 5[x]DownValue/OwnValue conflicto

que sé acerca de la localización variables, pero prefiero usar variables globales al principio del desarrollo.

No puedo pensar en una razón legítima para mezclar OwnValues ​​y DownValues. ¿Hay alguna manera de implementar un mensaje de advertencia cuando ocurre una situación como la anterior?

Además de consejos a continuación, el contexto por defecto se pueden encontrar en OptionsInspector bajo Opciones de celda/Opciones de evaluación/CellContext

Respuesta

11

Puede utilizar Protect[f] para evitar mayores asignaciones (de cualquier tipo) y Unprotect[f] para permitir de nuevo.

También podría hacer algunas hackery sencillo con hasta valores para evitar Set[f, ...] de tener que poner propios valores en f pero todavía permite la asignación de valores de abajo sin tener que utilizar Protect/Unprotect:

In[76]:= ClearAll[f] 

In[77]:= f /: Set[f, x_] := x 

In[78]:= f = 7 

Out[78]= 7 

In[79]:= f 

Out[79]= f 

In[80]:= f[x_] := x + 1 

In[81]:= f[1] 

Out[81]= 2 

Lo anterior bloquea de forma transparente el uso de Set en f. La emisión de un mensaje real es sencillo también:

In[93]:= f::noov = "Blocked attempt to assign `1` as an OwnValue of f"; 

In[94]:= f /: Set[f, x_] := (Message[f::noov, x]; x) 

In[95]:= f = 7 

During evaluation of In[95]:= f::noov: Blocked attempt to assign 7 as 
    an OwnValue of f 

Out[95]= 7 
+0

¿Qué piensas sobre anular Set/SetDelayed para imprimir un mensaje de advertencia si hay conflicto con DownValue/OwnValue? –

+1

Probablemente sea posible, pero probablemente frágil. ¿Ha considerado usar contextos en su lugar ('Begin' /' End') o establecer contextos a nivel de celda/portátil? –

+0

+1, no había pensado en usar valores como ese. Inteligente. Además, usted hace una buena observación sobre los contextos de nivel celular/portátil; He encontrado que es una de las mejoras más útiles desde la v. 5. – rcollyer

3

esto no responde a la pregunta original sobre la generación de un mensaje de advertencia, pero Formal Symbols son muy útiles para su uso como símbolos globales. Están protegidos automáticamente y, por lo tanto, no pueden redefinirse accidentalmente. Ingrese un símbolo formal usando las teclas <ESC>$f</ESC>, donde f puede ser cualquier letra. La desventaja es que se requieren cuatro teclas para ingresar el símbolo en lugar de uno.

+0

+1 para el tidbit útil. ¿Es posible generar programáticamente (por ejemplo, dentro de un paquete) símbolos formales a partir de letras dobles o griegas? Si no, supongo que los ejemplos de MakeBoxes en la documentación de Símbolos formales permitirían la sustitución (de carácter y/o color). Esto podría ser un truco de diseño realmente útil. :) – telefunkenvf14

+0

@ telefunkenvf14 Si se refiere a la apariencia visual distintiva de los símbolos formales (con los puntos arriba y abajo), no sé de una manera de generar otros símbolos similares. Por lo que puedo decir, las letras punteadas son caracteres en una fuente especial. Uno probablemente podría acercarse usando 'Underoverscript' y' Symbolize' pero los resultados podrían ser una molestia para ingresar desde el teclado. Las otras características de los símbolos formales, que carecen de definiciones integradas y están protegidas por 'Protect', son fáciles de organizar para cualquier otro símbolo. – WReach