sql >> Base de Datos >  >> Database Tools >> MySQL Workbench

Evaluación no deseada en tareas en Mathematica:¿por qué sucede y cómo depurarla durante la carga del paquete?

Dejando de lado el WB (que en realidad no es necesario para responder a su pregunta), el problema parece tener una respuesta sencilla basada solo en cómo se evalúan las expresiones durante las tareas. Aquí hay un ejemplo:

In[1505]:= 
notGoodQ[x_]:=True;
Clear[g];
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])

In[1509]:= g/:cccQ[g[x0_]]:=True

During evaluation of In[1509]:= g::nogood: -- Message text not found -- (x0_)
Out[1509]= $Aborted

Para que funcione, deliberadamente hice una definición para notGoodQ para devolver siempre True . Ahora, ¿por qué g[x0_] evaluado durante la asignación a través de TagSetDelayed ? La respuesta es que, mientras TagSetDelayed (así como SetDelayed ) en una asignación h/:f[h[elem1,...,elemn]]:=... no aplica ninguna regla que f puede tener, evaluará h[elem1,...,elem2] , así como f . Aquí hay un ejemplo:

In[1513]:= 
ClearAll[h,f];
h[___]:=Print["Evaluated"];

In[1515]:= h/:f[h[1,2]]:=3

During evaluation of In[1515]:= Evaluated
During evaluation of In[1515]:= TagSetDelayed::tagnf: Tag h not found in f[Null]. >>
Out[1515]= $Failed  

El hecho de que TagSetDelayed es HoldAll no significa que no evalúe sus argumentos, solo significa que los argumentos le llegan sin evaluar, y si serán evaluados o no depende de la semántica de TagSetDelayed (que describí brevemente arriba). Lo mismo vale para SetDelayed , por lo que la declaración de uso común de que "no evalúa sus argumentos" no es literalmente correcta. Una declaración más correcta es que recibe los argumentos sin evaluar y los evalúa de una manera especial:no evalúa la derecha, mientras que para la izquierda, evalúa la cabeza y los elementos, pero no aplica reglas para la cabeza. Para evitar eso, puede envolver las cosas en HoldPattern , así:

Clear[g,notGoodQ];
notGoodQ[x_]:=EvenQ[x];
g[x_?notGoodQ]:=(Message[g::nogood,x];Abort[])
g/:cccQ[HoldPattern[g[x0_]]]:=True;

Esto pasa. Aquí hay algunos usos:

In[1527]:= cccQ[g[1]]
Out[1527]= True

In[1528]:= cccQ[g[2]]
During evaluation of In[1528]:= g::nogood: -- Message text not found -- (2)
Out[1528]= $Aborted

Tenga en cuenta, sin embargo, que la necesidad de HoldPattern dentro de su lado izquierdo al hacer una definición a menudo es una señal de que la expresión dentro de su cabeza también puede evaluarse durante la llamada a la función, lo que puede romper su código. Aquí hay un ejemplo de lo que quiero decir:

In[1532]:= 
ClearAll[f,h];
f[x_]:=x^2;
f/:h[HoldPattern[f[y_]]]:=y^4;

Este código intenta detectar casos como h[f[something]] , pero obviamente fallará ya que f[something] evaluará antes de que la evaluación llegue a h :

In[1535]:= h[f[5]]
Out[1535]= h[25]

Para mí, la necesidad de HoldPattern en la izq. es una señal de que necesito reconsiderar mi diseño.

EDITAR

Con respecto a la depuración durante la carga en WB, una cosa que puede hacer (IIRC, no puede verificar en este momento) es usar declaraciones de impresión antiguas buenas, cuyo resultado aparecerá en la consola de WB. Personalmente, rara vez siento la necesidad de un depurador para este propósito (paquete de depuración al cargar)

EDITAR 2

En respuesta a la edición en la pregunta:

En cuanto al orden de las definiciones:sí, puedes hacer esto y resuelve este problema en particular. Pero, en general, esto no es sólido y no lo consideraría un buen método general. Es difícil dar un consejo definitivo para el caso que nos ocupa, ya que está un poco fuera de contexto, pero me parece que el uso de UpValues aquí es injustificado. Si esto se hace para el manejo de errores, hay otras formas para hacerlo sin usar UpValues .

Generalmente, UpValues se usan más comúnmente para sobrecargar alguna función de una manera segura, sin agregar ninguna regla a la función que se está sobrecargando. Un consejo es evitar asociar UpValues con encabezados que también tienen DownValues y puede evaluar:al hacer esto, comienza a jugar un juego con el evaluador y eventualmente perderá. Lo más seguro es adjuntar UpValues a símbolos inertes (cabezas, contenedores), que a menudo representan un "tipo" de objetos en los que desea sobrecargar una función determinada.

Con respecto a mi comentario sobre la presencia de HoldPattern indicando un mal diseño. Ciertamente hay hay usos legítimos de HoldPattern , como este (algo artificial):

In[25]:= 
Clear[ff,a,b,c];
ff[HoldPattern[Plus[x__]]]:={x};
ff[a+b+c]

Out[27]= {a,b,c} 

Aquí se justifica porque en muchos casos Plus permanece sin evaluar y es útil en su forma no evaluada, ya que se puede deducir que representa una suma. Necesitamos HoldPattern aquí por la forma Plus se define en un solo argumento, y porque un patrón pasa a ser un solo argumento (aunque generalmente describe múltiples argumentos) durante la definición. Entonces, usamos HoldPattern aquí para evitar tratar el patrón como un argumento normal, pero esto es en su mayoría diferente de los casos de uso previstos para Plus . Siempre que este sea el caso (estamos seguros de que la definición funcionará bien para los casos de uso previstos), HoldPattern está bien. Tenga en cuenta, por cierto, que este ejemplo también es frágil:

In[28]:= ff[Plus[a]]
Out[28]= ff[a]

La razón por la que todavía está bien es que normalmente no usamos Plus en un solo argumento.

Pero, hay un segundo grupo de casos, donde la estructura de los argumentos generalmente proporcionados es la misma que la estructura de los patrones utilizados para la definición. En este caso, la evaluación del patrón durante la asignación indica que la misma evaluación ocurrirá con los argumentos reales durante las llamadas a funciones. Su uso cae en esta categoría. Mi comentario para una falla de diseño fue para tales casos:puede evitar que el patrón se evalúe, pero tendrá que evitar que los argumentos también se evalúen para que esto funcione. Y la coincidencia de patrones con expresiones no evaluadas por completo es frágil. Además, la función nunca debe asumir algunas condiciones adicionales (más allá de lo que puede verificar) para los argumentos.