sql >> Databáze >  >> Database Tools >> MySQL Workbench

Nežádoucí hodnocení v úkolech v Mathematice:proč se to děje a jak to odladit během načítání balíčku?

Pomineme-li WB (která není k zodpovězení vaší otázky ve skutečnosti potřeba) – zdá se, že problém má přímou odpověď založenou pouze na tom, jak jsou výrazy vyhodnocovány během zadání. Zde je příklad:

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

Aby to fungovalo, schválně jsem vytvořil definici notGoodQ vždy vrátit True . Nyní, proč byl g[x0_] vyhodnoceno během přiřazení prostřednictvím TagSetDelayed ? Odpověď zní, že zatímco TagSetDelayed (stejně jako SetDelayed ) v přiřazení h/:f[h[elem1,...,elemn]]:=... neuplatňuje žádná pravidla, která f může mít, vyhodnotí h[elem1,...,elem2] , stejně jako f . Zde je příklad:

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  

Skutečnost, že TagSetDelayed je HoldAll neznamená, že své argumenty nevyhodnocuje – znamená to pouze, že argumenty k němu dorazí nevyhodnocené a zda budou nebo nebudou vyhodnoceny, závisí na sémantice TagSetDelayed (což jsem stručně popsal výše). Totéž platí pro SetDelayed , takže běžně používané tvrzení, že „nehodnotí své argumenty“, není doslova správné. Správnější tvrzení je, že argumenty přijímá nevyhodnocené a hodnotí je zvláštním způsobem - nehodnotí r.h.s, zatímco pro l.h.s. hodnotí hlavu a prvky, ale neaplikuje pravidla pro hlavu. Abyste tomu zabránili, můžete věci zabalit do HoldPattern , takto:

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

Tohle projde. Zde je nějaké použití:

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

Všimněte si však, že je potřeba HoldPattern uvnitř vaší levé strany při vytváření definice je často známkou toho, že výraz uvnitř vaší hlavy se může také vyhodnotit během volání funkce, což může narušit váš kód. Zde je příklad toho, co mám na mysli:

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

Tento kód se pokouší zachytit případy jako h[f[something]] , ale zjevně selže, protože f[something] vyhodnotí, než dojde k vyhodnocení h :

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

Pro mě je potřeba HoldPattern na l.h.s. je známkou toho, že musím přehodnotit svůj návrh.

UPRAVIT

Pokud jde o ladění během načítání ve WB, jedna věc, kterou můžete udělat (IIRC, nelze nyní zkontrolovat), je použít staré dobré tiskové příkazy, jejichž výstup se objeví v konzole WB. Osobně jen zřídka cítím potřebu debuggeru pro tento účel (ladící balíček při načítání)

ÚPRAVA 2

V reakci na úpravu v otázce:

Pokud jde o pořadí definic:ano, můžete to udělat a řeší tento konkrétní problém. Ale obecně to není robustní a nepovažoval bych to za dobrou obecnou metodu. Je těžké dát jednoznačnou radu pro daný případ, protože je trochu mimo jeho kontext, ale zdá se mi, že použití UpValues tady je to neopodstatněné. Pokud se tak děje kvůli zpracování chyb, existují jinými způsoby to udělat bez použití UpValues .

Obecně UpValues se nejčastěji používají k přetížení některé funkce bezpečným způsobem, aniž by se k přetěžované funkci přidalo nějaké pravidlo. Jednou radou je vyhnout se přiřazování UpValues s hlavami, které mají také DownValues a může vyhodnotit - tím začnete hrát hru s hodnotitelem a nakonec prohrajete. Nejbezpečnější je připojit UpValues na inertní symboly (hlavičky, kontejnery), které často představují „typ“ objektů, na které chcete danou funkci přetížit.

Pokud jde o můj komentář k přítomnosti HoldPattern což naznačuje špatný design. Určitě existují legitimní použití pro HoldPattern , jako je tento (poněkud umělý):

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

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

Zde je to oprávněné, protože v mnoha případech Plus zůstává nevyhodnocena a je užitečná ve své neohodnocené formě - protože lze odvodit, že představuje součet. Potřebujeme HoldPattern zde kvůli způsobu Plus je definován na jediném argumentu, a protože vzor je během definice náhodou jediným argumentem (i když obecně popisuje více argumentů). Takže používáme HoldPattern zde, aby se zabránilo zpracování vzoru jako normálního argumentu, ale to se většinou liší od zamýšlených případů použití pro Plus . Kdykoli tomu tak je (jsme si jisti, že definice bude fungovat správně pro zamýšlené případy použití), HoldPattern je v pořádku. Všimněte si, že tento příklad je také křehký:

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

Důvod, proč je to stále většinou v pořádku, je ten, že normálně nepoužíváme Plus na jediném argumentu.

Existuje však druhá skupina případů, kdy je struktura obvykle dodávaných argumentů stejná jako struktura vzorů použitých pro definici. V tomto případě vyhodnocení vzoru během přiřazení indikuje, že ke stejnému vyhodnocení dojde se skutečnými argumenty během volání funkce. Vaše použití spadá do této kategorie. Moje poznámka k chybě v návrhu byla pro takové případy - můžete zabránit vyhodnocení vzoru, ale budete muset zabránit také vyhodnocení argumentů, aby to fungovalo. A párování vzorů proti ne zcela vyhodnocenému výrazu je křehké. Funkce by také nikdy neměla převzít nějaké další podmínky (nad rámec toho, co může typově kontrolovat) pro argumenty.




  1. Zobrazení schématu sady výsledků v SQL Server Management Studio

  2. SQL Daily Vynikající prodeje, Rolling Aggregate?

  3. MySQL Workbench> Pluginy> Utilities> Reformat SQL Query

  4. MySQL PHPMyAdmin Error #1062 – Duplicitní záznam „0“ pro klíč „PRIMARY“