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

Oönskad utvärdering i uppgifter i Mathematica:varför det händer och hur man felsöker det under paketladdningen?

Om man bortser från WB (som egentligen inte behövs för att svara på din fråga) - så verkar problemet ha ett enkelt svar baserat enbart på hur uttryck utvärderas under uppdrag. Här är ett exempel:

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

För att få det att fungera gjorde jag medvetet en definition för notGoodQ för att alltid returnera True . Varför var g[x0_] utvärderas under uppdraget genom TagSetDelayed ? Svaret är att medan TagSetDelayed (samt SetDelayed ) i en uppgift h/:f[h[elem1,...,elemn]]:=... tillämpar inga regler som f kan ha, kommer den att utvärdera h[elem1,...,elem2] , samt f . Här är ett exempel:

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  

Det faktum att TagSetDelayed är HoldAll betyder inte att den inte utvärderar sina argument - det betyder bara att argumenten kommer till den outvärderade, och om de kommer att utvärderas eller inte beror på semantiken för TagSetDelayed (som jag kort beskrev ovan). Detsamma gäller för SetDelayed , så det vanliga påståendet att det "inte utvärderar sina argument" är inte bokstavligen korrekt. Ett mer korrekt påstående är att den tar emot argumenten outvärderade och utvärderar dem på ett speciellt sätt - inte utvärdera r.h.s, medan för l.h.s. utvärdera huvud och element men inte tillämpa regler för huvudet. För att undvika det kan du slå in saker i HoldPattern , så här:

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

Detta går igenom. Här är lite användning:

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

Observera dock att behovet av HoldPattern inuti din vänstra sida när du gör en definition är ofta ett tecken på att uttrycket inuti ditt huvud också kan utvärderas under funktionsanropet, vilket kan bryta din kod. Här är ett exempel på vad jag menar:

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

Den här koden försöker fånga fall som h[f[something]] , men det kommer uppenbarligen att misslyckas eftersom f[something] kommer att utvärdera innan utvärderingen kommer till h :

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

För mig är behovet av HoldPattern på l.h.s. är ett tecken på att jag måste ompröva min design.

REDIGERA

Angående felsökning under laddning i WB, en sak du kan göra (IIRC, kan inte kontrollera just nu) är att använda gamla gamla utskriftssatser, vars utdata kommer att visas i WB:s konsol. Personligen känner jag sällan ett behov av debugger för detta ändamål (felsökningspaket vid laddning)

REDIGERA 2

Som svar på redigeringen i frågan:

Angående definitionsordningen:ja, du kan göra detta, och det löser just detta problem. Men generellt sett är detta inte robust, och jag skulle inte anse det som en bra allmän metod. Det är svårt att ge ett bestämt råd för ett aktuellt fall, eftersom det är lite utanför sitt sammanhang, men det verkar som om användningen av UpValues här är obefogat. Om detta görs för felhantering, finns det andra sätt för att göra det utan att använda UpValues .

I allmänhet UpValues används oftast för att överbelasta någon funktion på ett säkert sätt, utan att lägga till någon regel för funktionen som överbelastas. Ett råd är att undvika att associera UpValues med huvuden som också har DownValues och kan utvärdera -genom att göra detta börjar du spela ett spel med evaluator och kommer så småningom att förlora. Det säkraste är att bifoga UpValues att inerta symboler (huvuden, behållare), som ofta representerar en "typ" av objekt på vilka du vill överbelasta en given funktion.

Angående min kommentar om förekomsten av HoldPattern indikerar en dålig design. Det finns verkligen legitima användningar av HoldPattern , som den här (något konstgjorda):

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

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

Här är det motiverat eftersom i många fall Plus förblir outvärderad och är användbar i sin outvärderade form - eftersom man kan dra slutsatsen att den representerar en summa. Vi behöver HoldPattern här på grund av sättet Plus definieras på ett enda argument, och eftersom ett mönster råkar vara ett enda argument (även om det generellt beskriver flera argument) under definitionen. Så vi använder HoldPattern här för att förhindra att mönstret behandlas som normalt argument, men detta skiljer sig mest från de avsedda användningsfallen för Plus . När så är fallet (vi är säkra på att definitionen kommer att fungera bra för avsedda användningsfall), HoldPattern är bra. Notera b.t.w. att detta exempel också är bräckligt:

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

Anledningen till att det fortfarande mestadels är OK är att vi normalt sett inte använder Plus på ett enda argument.

Men det finns en andra grupp av fall, där strukturen av vanligtvis tillhandahållna argument är densamma som strukturen för mönster som används för definitionen. I det här fallet indikerar mönsterutvärdering under uppdraget att samma utvärdering kommer att ske med faktiska argument under funktionsanropen. Din användning faller inom denna kategori. Min kommentar för ett designfel var för sådana fall - du kan förhindra att mönstret utvärderas, men du måste förhindra att argumenten också utvärderas för att få detta att fungera. Och mönstermatchning mot inte helt utvärderade uttryck är bräckligt. Funktionen bör heller aldrig anta några extra villkor (utöver vad den kan typkontrollera) för argumenten.




  1. Hur öppnar man en rpt-fil som en SQL-tabell?

  2. Ändra fält i databastabeller med PhpMyAdmin

  3. Varför fungerar TINYINT(1) som ett booleskt men inte INT(1)?

  4. Varför får jag Host '192.168.1.220' som inte får ansluta till denna MySQL-server?