MySQL Workbench
 sql >> Database >  >> Database Tools >> MySQL Workbench

Valutazione indesiderata nei compiti in Mathematica:perché succede e come eseguirne il debug durante il caricamento del pacchetto?

Lasciando da parte il WB (che non è realmente necessario per rispondere alla tua domanda), il problema sembra avere una risposta semplice basata solo su come vengono valutate le espressioni durante i compiti. Ecco un esempio:

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

Per farlo funzionare, ho deliberatamente creato una definizione per notGoodQ per restituire sempre True . Ora, perché era g[x0_] valutata durante l'assegnazione tramite TagSetDelayed ? La risposta è che, mentre TagSetDelayed (così come SetDelayed ) in un compito h/:f[h[elem1,...,elemn]]:=... non applica alcuna regola che f potrebbe avere, valuterà h[elem1,...,elem2] , così come f . Ecco un esempio:

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  

Il fatto che TagSetDelayed è HoldAll non significa che non valuti i suoi argomenti - significa solo che gli argomenti arrivano ad esso non valutati e se verranno valutati o meno dipende dalla semantica di TagSetDelayed (che ho brevemente descritto sopra). Lo stesso vale per SetDelayed , quindi l'affermazione comunemente usata che "non valuta i suoi argomenti" non è letteralmente corretta. Un'affermazione più corretta è che riceve gli argomenti non valutati e li valuta in un modo speciale - non valuta il r.h.s, mentre per l.h.s., valuta la testa e gli elementi ma non applica le regole per la testa. Per evitarlo, puoi avvolgere le cose in HoldPattern , in questo modo:

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

Questo passa. Ecco un po' di utilizzo:

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

Nota tuttavia che la necessità di HoldPattern all'interno del lato sinistro quando si crea una definizione è spesso un segno che l'espressione all'interno della testa può anche essere valutata durante la chiamata alla funzione, il che potrebbe interrompere il codice. Ecco un esempio di cosa intendo:

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

Questo codice tenta di rilevare casi come h[f[something]] , ma ovviamente fallirà poiché f[something] valuterà prima che la valutazione arrivi a h :

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

Per me, la necessità di HoldPattern sulla sinistra è un segno che devo riconsiderare il mio design.

MODIFICA

Per quanto riguarda il debug durante il caricamento in WB, una cosa che puoi fare (IIRC, non posso controllare in questo momento) è usare le buone vecchie istruzioni di stampa, il cui output apparirà nella console del WB. Personalmente, sento raramente la necessità di un debugger per questo scopo (debug del pacchetto durante il caricamento)

MODIFICA 2

In risposta alla modifica nella domanda:

Per quanto riguarda l'ordine delle definizioni:sì, puoi farlo e risolve questo particolare problema. Ma, in generale, questo non è robusto e non lo considererei un buon metodo generale. È difficile dare un consiglio preciso per un caso in questione, poiché è un po' fuori contesto, ma mi sembra che l'uso di UpValues qui è ingiustificato. Se questo viene fatto per la gestione degli errori, ci sono altri modi per farlo senza usare UpValues .

In genere, UpValues sono usati più comunemente per sovraccaricare alcune funzioni in modo sicuro, senza aggiungere alcuna regola alla funzione che viene sovraccaricata. Un consiglio è di evitare di associare UpValues con teste che hanno anche DownValues e può valutare - in questo modo inizi a giocare con un valutatore e alla fine perderai. La cosa più sicura è allegare UpValues a simboli inerti (teste, contenitori), che spesso rappresentano un "tipo" di oggetti su cui si vuole sovraccaricare una determinata funzione.

Per quanto riguarda il mio commento sulla presenza di HoldPattern indicando un cattivo design. Certamente ci sono usi legittimi di HoldPattern , come questo (un po' artificiale):

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

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

Qui è giustificato perché in molti casi Plus rimane non valutato, ed è utile nella sua forma non valutata - poiché si può dedurre che rappresenta una somma. Abbiamo bisogno di HoldPattern qui per via del Plus è definito su un singolo argomento e perché un modello sembra essere un singolo argomento (anche se descrive generalmente più argomenti) durante la definizione. Quindi, utilizziamo HoldPattern qui per evitare di trattare il modello come un argomento normale, ma questo è per lo più diverso dai casi d'uso previsti per Plus . Ogni volta che questo è il caso (siamo sicuri che la definizione funzionerà bene per i casi d'uso previsti), HoldPattern è ok. Nota tra l'altro che anche questo esempio è fragile:

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

Il motivo per cui è ancora per lo più OK è che normalmente non usiamo Plus su un singolo argomento.

Ma esiste un secondo gruppo di casi, in cui la struttura degli argomenti normalmente forniti è la stessa della struttura dei modelli usati per la definizione. In questo caso, la valutazione del modello durante l'assegnazione indica che la stessa valutazione avverrà con argomenti effettivi durante le chiamate di funzione. Il tuo utilizzo rientra in questa categoria. Il mio commento per un difetto di progettazione era per questi casi:puoi impedire la valutazione del modello, ma dovrai impedire anche la valutazione degli argomenti, affinché funzioni. E il pattern-matching rispetto all'espressione non completamente valutata è fragile. Inoltre, la funzione non dovrebbe mai assumere alcune condizioni extra (oltre a ciò che può controllare il tipo) per gli argomenti.