MySQL Workbench
 sql >> Base de données >  >> Database Tools >> MySQL Workbench

Évaluation indésirable dans les devoirs dans Mathematica :pourquoi cela se produit-il et comment le déboguer lors du chargement du paquet ?

Laissant de côté le WB (qui n'est pas vraiment nécessaire pour répondre à votre question) - le problème semble avoir une réponse simple basée uniquement sur la façon dont les expressions sont évaluées pendant les affectations. Voici un exemple :

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

Pour que cela fonctionne, j'ai délibérément créé une définition pour notGoodQ pour toujours retourner True . Maintenant, pourquoi était g[x0_] évalué pendant l'affectation via TagSetDelayed ? La réponse est que, alors que TagSetDelayed (ainsi que SetDelayed ) dans une affectation h/:f[h[elem1,...,elemn]]:=... n'applique aucune règle qui f peut avoir, il évaluera h[elem1,...,elem2] , ainsi que f . Voici un exemple :

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  

Le fait que TagSetDelayed est HoldAll ne signifie pas qu'il n'évalue pas ses arguments - cela signifie seulement que les arguments lui arrivent non évalués, et qu'ils soient ou non évalués dépend de la sémantique de TagSetDelayed (que j'ai décrit brièvement ci-dessus). Il en va de même pour SetDelayed , de sorte que l'affirmation couramment utilisée selon laquelle il "n'évalue pas ses arguments" n'est pas littéralement correcte. Une déclaration plus correcte est qu'il reçoit les arguments non évalués et les évalue d'une manière spéciale - n'évalue pas les r.h.s., tandis que pour l.h.s., évalue la tête et les éléments mais n'applique pas de règles pour la tête. Pour éviter cela, vous pouvez envelopper les choses dans HoldPattern , comme ceci :

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

Cela passe. Voici quelques utilisations :

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

Notez cependant que le besoin de HoldPattern à l'intérieur de votre côté gauche lorsque vous faites une définition est souvent un signe que l'expression à l'intérieur de votre tête peut également être évaluée lors de l'appel de la fonction, ce qui peut casser votre code. Voici un exemple de ce que je veux dire :

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

Ce code tente d'attraper des cas comme h[f[something]] , mais cela échouera évidemment puisque f[something] évaluera avant que l'évaluation n'arrive à h :

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

Pour moi, le besoin de HoldPattern sur la gauche est un signe que je dois reconsidérer ma conception.

MODIFIER

En ce qui concerne le débogage lors du chargement dans WB, une chose que vous pouvez faire (IIRC, ne peut pas vérifier pour le moment) est d'utiliser de bonnes vieilles instructions d'impression, dont la sortie apparaîtra dans la console de WB. Personnellement, je ressens rarement le besoin d'un débogueur à cet effet (débogage du paquet lors du chargement)

MODIFICATION 2

En réponse à la modification de la question :

Concernant l'ordre des définitions :oui, vous pouvez le faire, et cela résout ce problème particulier. Mais, généralement, ce n'est pas robuste, et je ne considérerais pas cela comme une bonne méthode générale. Il est difficile de donner un conseil précis pour un cas concret, car il est un peu hors de son contexte, mais il me semble que l'utilisation de UpValues ici est injustifié. Si cela est fait pour la gestion des erreurs, il y a d'autres manières pour le faire sans utiliser UpValues .

Généralement, UpValues sont utilisés le plus souvent pour surcharger certaines fonctions de manière sûre, sans ajouter de règle à la fonction surchargée. Un conseil est d'éviter d'associer UpValues avec des têtes qui ont aussi DownValues et peut évaluer - en faisant cela, vous commencez à jouer à un jeu avec évaluateur, et finirez par perdre. Le plus sûr est d'attacher UpValues aux symboles inertes (têtes, conteneurs), qui représentent souvent un "type" d'objets sur lesquels on veut surcharger une fonction donnée.

Concernant mon commentaire sur la présence de HoldPattern indiquant une mauvaise conception. Il y en a certainement il y en a utilisations légitimes de HoldPattern , comme celle-ci (quelque peu artificielle) :

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

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

Ici, c'est justifié car dans de nombreux cas Plus reste non évalué, et est utile sous sa forme non évaluée - puisqu'on peut en déduire qu'il représente une somme. Nous avons besoin de HoldPattern ici à cause de la façon dont Plus est défini sur un seul argument, et parce qu'un motif se trouve être un seul argument (même s'il décrit généralement plusieurs arguments) lors de la définition. Donc, nous utilisons HoldPattern ici pour éviter de traiter le modèle comme un argument normal, mais cela est principalement différent des cas d'utilisation prévus pour Plus . Chaque fois que c'est le cas (nous sommes sûrs que la définition fonctionnera correctement pour les cas d'utilisation prévus), HoldPattern c'est bien. Notez d'ailleurs que cet exemple est également fragile :

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

La raison pour laquelle c'est encore généralement correct est que normalement nous n'utilisons pas Plus sur un seul argument.

Mais, il existe un deuxième groupe de cas, où la structure des arguments habituellement fournis est la même que la structure des motifs utilisés pour la définition. Dans ce cas, l'évaluation de modèle pendant l'affectation indique que la même évaluation se produira avec des arguments réels pendant les appels de fonction. Votre utilisation entre dans cette catégorie. Mon commentaire pour un défaut de conception était pour de tels cas - vous pouvez empêcher l'évaluation du modèle, mais vous devrez également empêcher les arguments d'évaluer, pour que cela fonctionne. Et le pattern-matching contre une expression non complètement évaluée est fragile. De plus, la fonction ne doit jamais supposer des conditions supplémentaires (au-delà de ce qu'elle peut vérifier par type) pour les arguments.