MySQL Workbench
 sql >> Baza danych >  >> Database Tools >> MySQL Workbench

Niechciana ocena w zadaniach w Mathematica:dlaczego tak się dzieje i jak debugować podczas ładowania pakietu?

Pomijając WB (który nie jest tak naprawdę potrzebny do odpowiedzi na twoje pytanie) - problem wydaje się mieć prostą odpowiedź opartą tylko na tym, jak wyrażenia są oceniane podczas zadań. Oto przykład:

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 zadziałało, celowo stworzyłem definicję notGoodQ aby zawsze zwracać True . Teraz, dlaczego był g[x0_] oceniane podczas przypisania przez TagSetDelayed ? Odpowiedź jest taka, podczas gdy TagSetDelayed (jak również SetDelayed ) w przypisaniu h/:f[h[elem1,...,elemn]]:=... nie stosuje żadnych reguł, które f może mieć, oceni h[elem1,...,elem2] , a także f . Oto przykład:

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  

Fakt, że TagSetDelayed to HoldAll nie oznacza, że ​​nie ocenia swoich argumentów - oznacza to tylko, że argumenty docierają do niego bez oceny, a to, czy zostaną ocenione, zależy od semantyki TagSetDelayed (co krótko opisałem powyżej). To samo dotyczy SetDelayed , więc powszechnie używane stwierdzenie, że „nie ocenia swoich argumentów”, nie jest dosłownie poprawne. Bardziej poprawnym stwierdzeniem jest to, że otrzymuje argumenty nieocenione i ocenia je w specjalny sposób - nie ocenia prawej strony, podczas gdy dla lewej ocenia głowę i elementy, ale nie stosuje reguł dla głowy. Aby tego uniknąć, możesz zawinąć rzeczy w HoldPattern , tak:

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

To przechodzi. Oto niektóre zastosowania:

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

Zauważ jednak, że potrzeba HoldPattern wewnątrz twojej lewej strony podczas tworzenia definicji jest często znak, że wyrażenie wewnątrz twojej głowy może również zostać ocenione podczas wywołania funkcji, co może zepsuć twój kod. Oto przykład tego, co mam na myśli:

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

Ten kod próbuje wyłapać przypadki takie jak h[f[something]] , ale oczywiście zawiedzie, ponieważ f[something] oceni, zanim ocena dojdzie do h :

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

Dla mnie potrzeba HoldPattern po lewej stronie to znak, że muszę ponownie przemyśleć swój projekt.

EDYTUJ

Jeśli chodzi o debugowanie podczas ładowania w WB, jedną rzeczą, którą możesz zrobić (IIRC, nie mogę teraz sprawdzić) jest użycie starych dobrych instrukcji print, których wynik pojawi się w konsoli WB. Osobiście rzadko odczuwam potrzebę debuggera do tego celu (pakiet debugowania podczas ładowania)

EDYTUJ 2

W odpowiedzi na zmianę w pytaniu:

Jeśli chodzi o kolejność definicji:tak, możesz to zrobić i to rozwiązuje ten konkretny problem. Ale generalnie nie jest to solidne i nie uważałbym tego za dobrą ogólną metodę. Trudno jest dać konkretną radę dla danej sprawy, ponieważ jest ona nieco poza kontekstem, ale wydaje mi się, że użycie UpValues tutaj jest nieuzasadnione. Jeśli jest to zrobione w przypadku obsługi błędów, istnieją inne sposoby zrobić to bez użycia UpValues .

Ogólnie UpValues są używane najczęściej do przeciążania niektórych funkcji w bezpieczny sposób, bez dodawania żadnej reguły do ​​przeciążanej funkcji. Jedną z rad jest unikanie kojarzenia UpValues z głowicami, które również mają DownValues i może ocenić - robiąc to, zaczynasz grać w grę z oceniającym i ostatecznie przegrywasz. Najbezpieczniej jest dołączyć UpValues na symbole obojętne (nagłówki, pojemniki), które często reprezentują "typ" obiektów, na których chcesz przeciążyć daną funkcję.

Odnośnie mojego komentarza na temat obecności HoldPattern wskazując na zły projekt. Z pewnością legalne zastosowania dla HoldPattern , na przykład ten (nieco sztuczny):

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

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

Tutaj jest to uzasadnione, ponieważ w wielu przypadkach Plus pozostaje nieoceniony i jest użyteczny w swojej nieocenionej postaci - ponieważ można wywnioskować, że reprezentuje sumę. Potrzebujemy HoldPattern tutaj ze względu na sposób Plus jest zdefiniowany na pojedynczym argumencie i ponieważ wzorzec jest pojedynczym argumentem (nawet jeśli ogólnie opisuje wiele argumentów) podczas definicji. Używamy więc HoldPattern tutaj, aby zapobiec traktowaniu wzorca jako normalnego argumentu, ale w większości różni się to od zamierzonych przypadków użycia dla Plus . W każdym przypadku (jesteśmy pewni, że definicja będzie działać poprawnie w zamierzonych przypadkach użycia), HoldPattern jest w porządku. Zwróć uwagę, że ten przykład jest również delikatny:

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

Powodem, dla którego nadal jest to w większości OK, jest to, że zwykle nie używamy Plus na jednym argumencie.

Istnieje jednak druga grupa przypadków, w których struktura zwykle podawanych argumentów jest taka sama, jak struktura wzorców użytych do definicji. W takim przypadku ocena wzorca podczas przypisania wskazuje, że ta sama ocena nastąpi z rzeczywistymi argumentami podczas wywołań funkcji. Twoje użycie należy do tej kategorii. Mój komentarz dotyczący błędu projektowego dotyczył takich przypadków - możesz uniemożliwić ocenę wzorca, ale będziesz musiał również uniemożliwić ocenę argumentów, aby to zadziałało. A dopasowywanie wzorców do nie do końca przeanalizowanego wyrażenia jest kruche. Ponadto funkcja nigdy nie powinna zakładać żadnych dodatkowych warunków (poza tym, co może sprawdzić typ) dla argumentów.




  1. DBeaver
  2.   
  3. phpMyAdmin
  4.   
  5. Navicat
  6.   
  7. SSMS
  8.   
  9. MySQL Workbench
  10.   
  11. SQLyog
  1. Akcje głównego paska narzędzi Eclipse Kepler RCP

  2. Zapytanie SQL działa w środowisku roboczym, ale otrzymuje błąd „Nie można przekonwertować typu wariantu” z dokładnie tym samym zapytaniem w Delphi

  3. Obszar roboczy Eclipse ulega awarii podczas uruchamiania

  4. Jak zintegrować projekt KIE Workbench 6.1.0.Final (Drools Guvnor) z aplikacją Java?

  5. Jak sprawić, by FIO odtwarzał ślad z wieloma wątkami?