wolfram-mathematica
Zamówienie ewaluacyjne
Szukaj…
Uwagi
Ma to wyjaśnić kolejność oceny tak jednoznacznie, jak to możliwe. Prawdopodobnie mniej nadaje się jako wprowadzenie do wykonywania Mathematica. Opiera się on na stronie tutorial/Evaluation Mathematiki, wyjaśniając kolejność stosowania różnych reguł i wyjaśniając, które funkcje są traktowane specjalnie przez silnik oceny.
Konteksty oceny
W dowolnym momencie kod jest wykonywany w kontekście. Kontekst składa się z zestawu reguł zastępczych (jego słownika) i priorytetu, w którym należy je ocenić. Grupujemy pięć rodzajów kontekstów z odrębnymi zachowaniami i ograniczeniami: * Ustaw kontekst * Blokuj kontekst * Dopasowany kontekst * Zamień cały kontekst * Zastąp powtórzony kontekst
Ustaw konteksty
Kontekst zestawu jest zdefiniowany przez pewien zestaw operacji Set [] (funkcja częściej zapisywana = ). Głównym przykładem jest podstawowe środowisko wykonawcze. Jego słownik jest modyfikowany za każdym razem, gdy Set [] jest uruchamiany na zmiennej, która nie ma innego zasięgu. Inne instancje kontekstów zestawu wynikają z pakietów. Kontekst pakietu jest powiązany z kontekstem nadrzędnym w tym InnerPackageName\ że wszelkie wzorce w pakiecie stają się wzorcami w kontekście nadrzędnym, z odpowiednim prefiksem (definicja foo[x_]=3*x staje się InnerPackageName\ foo [x _] = 3 * x `).
Konteksty zestawu mogą zawierać tylko reguły, które mają powiązany „Tag”, ciąg powiązany z głową, aby szybciej zidentyfikować zastosowanie reguły. Aplikacja Set[yyy_,zzz_] określi Tag, sprawdzając, czy yyy jest symbolem. Jeśli tak, to jest to Tag. W przeciwnym razie sprawdza yyy[[0]] , a następnie yyy[[0,0]] i tak dalej. Jeśli w którymś momencie zostanie to określone jako symbol, jest to traktowane jako Tag. Jeśli zamiast tego jest atomem niebędącym symbolem (takim jak String, Integer, Real ...), wygeneruje błąd i żadna reguła nie zostanie utworzona.
Funkcje UpSet (napisane ^= ) i TagSet (napisane /: / = ) (oraz ich kuzyni UpSetDelayed i TagSetDelayed) pozwalają na powiązanie reguły z innym znacznikiem. Nadal istnieje ograniczenie, że Tag musi być symbolem. UpSet powiąże go z każdym argumentem w wyrażeniu lub jego głową, jeśli są funkcją z symbolem głowy. Na przykład wywołanie UpSet na f[a,b,c+d,e[f,g],5,h[i][j][k],p_] utworzoną regułę z a , b , e , i h . Argumenty c+d , 5 i p_ nie będą z nimi powiązane i spowodują wyświetlenie komunikatu o błędzie. Przypisanie nadal będzie skuteczne dla każdego z argumentów i (co zostanie wyjaśnione później w kolejności oceny) nadal będzie działać dla prawie wszystkich celów. TagSet przypomina UpSet, ale możesz podać dokładnie jeden symbol dla Tagu. Symbol musi wciąż być czymś, co może być ustawione przez Set lub UpSet (symbol najwyższego poziomu w głowie lub argumentach). Na przykład TagSet[f, f[a,b[c]], 2] jest akceptowalny i połączy definicję f ; TagSet[a, f[a,b[c]], 2] i TagSet[b, f[a,b[c]], 2] są również dopuszczalne, ale TagSet[c, f[a,b[c]], 2] nie jest.
Reguły w kontekście wymagają priorytetu aplikacji, ponieważ może istnieć wiele reguł, które dotyczą danego wyrażenia. (Dotyczy to również kontekstów ReplaceAll i ReplaceRepeated, ale radzą sobie z tym zupełnie inaczej). Priorytet ma na ogół odpowiadać specyfice wzorca. Biorąc pod uwagę wyrażenie a[q][b[c,d],e[f,g]] do oceny, z głową i argumentami ocenianymi tak dokładnie, jak to będzie (patrz poniżej DO ZROBIENIA), zacznij od szukania reguł oznakowanych z b które mają zastosowanie; następnie reguły oznaczone e ; następnie zachowaniem zasad tagiem . a W ramach każdego zestawu reguł utrzymywana jest kolejność na tych związanych z danym symbolem. Reguły bez spacji (takie jak f[a,b]=3 ) są automatycznie umieszczane na górze i sortowane w porządku kanonicznym (w kolejności sortowania). Za każdym razem, gdy dodawana jest nowa reguła, jądro przechodzi przez listę; jeśli jakaś reguła ma dokładnie taki sam LHS, to zostaje zastąpiona na miejscu. W przeciwnym razie dokonuje porównania specyficzności. Jeśli reguła X znajdująca się już na liście zostanie określona jako „mniej szczegółowa” niż nowa reguła Y, wówczas Y zostanie umieszczone bezpośrednio przed X. W przeciwnym razie przejdzie przez listę. Jeśli żadna reguła nie jest mniej szczegółowa, reguła jest umieszczana na końcu listy. Sprawdzanie specyficzności jest bardziej skomplikowane i podane bardziej szczegółowo w poniższej sekcji.
Specyfika reguły
* Jeśli dwa wyrażenia nie mają wystąpienie BlankSequence ( __ ), BlankNullSequence ( ___ ), opcjonalnie ( : ), Alternatywy ( | ), powtarzające się ( .. ), RepeatedNull ( ... ) lub opcjonalnych argumentów ( _. ), A następnie można je porównać strukturalnie. Biorąc pod uwagę dwa równoważne drzewa wyrażeń X i Y, gdzie wszystkie odstępy w Y są również odstępami w X, ale X ma odstępy, w których Y nie, wtedy Y jest bardziej specyficzny. * Jeśli dwa wyrażenia są równoważne, z wyjątkiem tego, że niektóre wystąpienia _ zostały zastąpione przez __ w drugim wyrażeniu lub __ zostały zastąpioneh ___ , to pierwsze jest bardziej szczegółowe. * W przypadku rozbiórki jeden więcej opcjonalnych ( : ) (lub opcjonalnie _. ) Warunki daje inny wyraz, po czym ten ostatni jest bardziej szczegółowy. * Jeśli pewien zestaw opcji z Alternatyw daje inne wyrażenie, to drugie jest bardziej szczegółowe. * Jeśli zastąpienie wszystkich instancji RepeatedNull[foo] Repeated[foo] lub Repeated[foo] foo , daje inne wyrażenie, to drugie jest bardziej szczegółowe * Niektóre kombinacje tych reguł można zastosować jednocześnie, ale nie jest to obecnie wiedzieć, jakie są tego przypadki. * Kombinacje wyrażeń, takie jak _List i {___} teoretycznie, powinny traktować je identycznie, ale porównanie wydaje się dziwnie zależne od kontekstu, od czasu do czasu klasyfikując je w taki czy inny sposób.
Blokuj kontekst
Kontekst bloku jest bardziej restrykcyjny, ponieważ LHS reguły w bloku może być tylko symbolem. To znaczy, tylko definicje postaci f=2+x , a nie f[x_]=2+x . (Należy zauważyć, że z praktycznego punktu widzenia funkcje można nadal konstruować z definicjami, takimi jak `Ustaw [Blok jest powiązany z jego kontekstem nadrzędnym, ponieważ wszelkie nowe definicje podczas oceny bloku są normalnie przekazywane do otoczonego kontekstu, ale „ukryje” pewien zestaw zmiennych, zapewniając definicje, które mogą ukryć definicje otaczającego kontekstu. Definicje z kontekstu otaczającego są nadal dostępne podczas oceny wewnętrznego wyrażenia. Ponieważ definicję można powiązać tylko z symbolem, nie ma pojęcia o priorytecie jak wyżej.
Dopasowany kontekst
Po dopasowaniu reguły istnieją lokalnie powiązane definicje zmiennych. Dzieje się to leksykalnie . Innymi słowy, podporządkowuje się związanym definicjom zmiennych w wyrażeniu, nie oceniając niczego innego. Dopiero po wystąpieniu wszystkich subskrypcji zaczyna ponownie oceniać wyrażenie jako całość od góry. Podstawowym sposobem tworzenia dopasowanych kontekstów jest reguła z zestawu kontekstu lub reguły. Na przykład w
g[a_]:=a+x;
f[x_]:=x+g[1];
f[x^2]
(*Yields 1+x+x^2 *)
Po dopasowaniu reguły f[x_] do f[y] , symbol x jest powiązany z wartością x^2 . Dokonuje jednego podstawienia, ale ponieważ nie ocenia g , zwraca x^2+g[1] . Jest to następnie ponownie analizowane w otaczającym kontekście zestawu i staje się 1+x+x^2 . Istotna różnica w ocenie w dopasowanym kontekście polega na tym, że zamiana nie jest rekurencyjna. Gdy podpisze x->x^2 , nie powtarza się nawet na własnych wynikach.
Dopasowane konteksty są również tworzone przez With , Module , Function i Replace . Wiele innych funkcji tworzy je wewnętrznie, na przykład Plot używa tego typu kontekstu do oceny wyrażenia, które ma zostać wydrukowane.
ReplaceRepeated Context
Kontekst ReplaceRepeated jest tworzony, gdy wystąpi jakakolwiek aplikacja ReplaceRepeated . Wyróżnia się to tym, że może mieć z reguły dowolne wyrażenie LHS, w tym wyrażenia bez znacznika, takie jak _[_] . W tym sensie jest to najbardziej elastyczny kontekst. Może również zawierać kilka reguł, które mogą powodować konflikty, więc musi zachować priorytet. Kontekst ReplaceRepeated zastosuje pierwszą regułę na liście, tam gdzie ma to zastosowanie. Jeśli nie pasuje, przechodzi do drugiego i tak dalej. Jeśli w którymś momencie reguła pasuje, wraca do pierwszej reguły i zaczyna od nowa. Jeśli w dowolnym momencie nastąpi zastosowanie reguły i nie nastąpi żadna zmiana, zostanie ona zamknięta - nawet jeśli inne reguły później na liście dokonałyby zmiany. Oznacza to, że wszelkie mniej szczegółowe reguły znajdujące się wcześniej na liście zapobiegną późniejszemu użyciu reguł. Ponadto umieszczenie a_->a na początku listy reguł spowoduje natychmiastowe zakończenie całego ReplaceRepeated .
ReplaceAll Context
Kontekst ReplaceAll jest tworzony, gdy wystąpi jakakolwiek aplikacja ReplaceAll . Jego działanie jest podobne do działania ReplaceRepeated, ponieważ jego priorytet zastosowania reguły jest uporządkowany na liście, gdy dwa mogą stosować oba na tym samym poziomie wyrażenia. Jednak przypomina dopasowany kontekst, ponieważ zamieniona zawartość nie jest poddawana dalszej ocenie, nawet według późniejszych reguł . Na przykład x/.{x->y,y->z} daje y . Dlatego niepoprawne jest przeglądanie aplikacji ReplaceAll, która stosuje kolejno każdą regułę. Zamiast tego przemierza drzewo, szukając odpowiednich reguł. Gdy znajdzie coś pasującego, wykonuje zamianę, a następnie wraca do drzewa, nie przechodząc przez nowe drzewo. Warto również zauważyć, że stara się stosować reguły od góry do dołu, w wyniku czego prawdopodobnie nie działa w kolejności na liście. Na przykład,
Cos[1 + 2 Sqrt[Sin[x]]] /. {Cos[_] -> 5, Sin[_] :> (Print[1]; 10)}
Cos[1 + 2 Sqrt[Sin[x]]] /. {Sin[_] :> (Print[1]; 10), Cos[_] -> 5}
oba dają 5 bez drukowania. Ponieważ Cos[_] odpowiada wyższemu poziomowi drzewa, stosuje go jako pierwszy.
Hold i Evaluate oraz zlecenie wykonania
Kolejność oceny, podana w wyrażeniu, przebiega następująco: * Oceń głowę tak dokładnie, jak to możliwe * Jeśli głowa ma właściwość Hold ( HoldFirst , HoldRest , HoldAll , HoldAllComplete ), to * Sprawdź odpowiednie argumenty. O ile nie jest to HoldAllComplete , sprawdź, czy głowa to Evaluate . Jeśli tak jest, usuń pasek Evaluate i zaznacz go do oceny. * Sprawdź argumenty dla instancji Unevaluated i Unevaluated je w razie potrzeby, chyba że właściwość HoldAllComplete jest obecna. * Spłaszcz argumenty z Sequence s, chyba że SequenceHold . * Zastosuj atrybuty Flat , Listable , Orderless Listable , jeśli dotyczy. * Zastosuj ocenę związaną z wartościami argumentu argumentu (ich tagi) * Zastosuj ocenę związaną z głową.
Gdy ocena wyrażenia jest zakończona, jest oznaczana jako w pełni oceniona. Kolejne oceny, które uderzą w to wyrażenie, nie będą próbowały go ocenić. Jeśli nowa reguła jest zdefiniowana dla symbolu występującego w środku, flaga jest usuwana i można ją ponownie ocenić. Godne uwagi miejsce, w którym „to się nie udaje” to Condition ( \; ): reguła warunkowa może nie mieć zastosowania przy początkowej ocenie. Jeśli niezwiązany symbol zmienia wartości, a teraz warunek ma zastosowanie, wyrażenie jest nadal oznaczone jako w pełni ocenione i nie zmieni się w wyniku. Funkcja Update jest wyjątkowa, ponieważ ocenia swój argument niezależnie od tego, czy został już oceniony, czy nie, wymuszając pewnego rodzaju „opróżnianie pamięci podręcznej”.
Istnieje szereg innych funkcji, które są często uważane za wyjątkowy, taki Hold , Defer , ReplacePart , Extract lub ReleaseHold . Wszystkie te efekty można osiągnąć za pomocą atrybutów (takich jak HoldAll ) i normalnej definicji funkcji i nie muszą być one traktowane jednoznacznie przez ewaluatora.
Zastosowanie `ReplaceAll` i` ReplaceRepeated`
Przykład, w jaki sposób ReplaceAll stosuje regułę tylko raz, podczas gdy ReplaceRepeated zrobi to w pętli, ale zawsze ponownie uruchomi aplikację od pierwszej reguły.
x + a /. {
a_ + z :> (Print[0]; DoneA),
a_ + x :> (Print[1]; y + z),
a_ + y :> (Print[2]; DoneB)}
(* Prints "1", yields "y+z" *)
x + a //. {
a_ + z :> (Print[0]; DoneA),
a_ + x :> (Print[1]; y + z),
a_ + y :> (Print[2]; DoneB)}
(* Prints "1", then prints "0", yields "DoneA" *)
Sortowanie bąbelkowe
Sortowanie bąbelkowe z zasadami i zamiennikami:
list = {1, 4, 2, 3, 6, 7, 8, 0, 1, 2, 5, 4}
list //. {fsts___, x_, y_, lsts___} :> {fsts, y, x, lsts} /; y < x
(*
Out[1] := {1, 4, 2, 3, 6, 7, 8, 0, 1, 2, 5, 4}
Out[1] := {0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8}
*)