Ricerca…


Osservazioni

Questo dovrebbe spiegare l'ordine di valutazione nel modo più ambiguo possibile. Probabilmente è meno adatto come introduzione all'esecuzione di Mathematica. Si basa sulla pagina tutorial/Evaluation di Mathematica spiegando l'ordine in cui vengono applicate le diverse regole e spiegando quali funzioni sono trattate in modo specifico dal motore di valutazione.

Contesti di valutazione

In qualsiasi momento, il codice è in esecuzione in un contesto. Un contesto consiste in un insieme di regole di sostituzione (il suo dizionario) e una priorità in cui dovrebbero essere valutate. Raggruppiamo cinque tipi di contesti con comportamenti distinti e restrizioni: * Imposta contesto * Blocco contesto * Contesto contesto * Sostituisci tutto Contesto * Sostituisci contesto ripetuto

Imposta contesti

Un Set Context è definito da alcune serie di operazioni Set [] (la funzione più comunemente scritta = ). L'esempio principale è l'ambiente di esecuzione principale. Il suo dizionario viene modificato ogni volta che un Set [] viene eseguito su una variabile che non è per altri scopi. Le altre istanze di Set Contexts derivano dai pacchetti. Un contesto del pacchetto è correlato al suo contesto genitore in quanto qualsiasi modello all'interno del pacchetto diventa anche pattern all'interno del contesto genitore, con un prefisso appropriato (una definizione foo[x_]=3*x diventa InnerPackageName\ foo [x _] = 3 * x `).

Set Contesti può contenere solo regole che hanno un "Tag" associato, una stringa associata alla testa per identificare più rapidamente l'applicabilità della regola. Un'applicazione di Set[yyy_,zzz_] determinerà un Tag controllando se yyy è un simbolo. Se lo è, allora è il Tag. Altrimenti, controlla yyy[[0]] , quindi yyy[[0,0]] e così via. Se a un certo punto si determina che si tratta di un simbolo, viene preso come tag. Se invece è un atomo non simbolico (come String, Integer, Real ...), genera un errore e non verrà creata alcuna regola.

Le funzioni UpSet (scritto ^= ) e TagSet (scritto /: / = ) (ei loro cugini UpSetDelayed e TagSetDelayed) consentono di associare una regola a un Tag diverso. C'è ancora la restrizione che il Tag debba essere un simbolo. UpSet lo assocerà a ciascuno degli argomenti nell'espressione, o alla loro testa se sono una funzione con un simbolo per una testa. Ad esempio, chiamando UpSet su f[a,b,c+d,e[f,g],5,h[i][j][k],p_] la regola creata a a , b , e , e h . Gli argomenti c+d , 5 e p_ non avranno nulla ad essi associato e causeranno la visualizzazione di un messaggio di errore. Il compito continuerà comunque su ciascuno degli argomenti e (come verrà chiarito più avanti nell'ordine di valutazione) continuerà a funzionare per quasi tutti gli scopi. TagSet è come UpSet, ma puoi specificare esattamente un simbolo per il Tag. Il simbolo deve essere ancora qualcosa che può essere impostato da Set o UpSet (un simbolo di livello superiore nella testa o gli argomenti). Ad esempio, TagSet[f, f[a,b[c]], 2] è accettabile e TagSet[f, f[a,b[c]], 2] la definizione con f ; TagSet[a, f[a,b[c]], 2] e TagSet[b, f[a,b[c]], 2] sono anche accettabili, ma TagSet[c, f[a,b[c]], 2] non lo è.

Le regole all'interno di un contesto richiedono una priorità per l'applicazione, poiché possono esistere molte regole applicabili a una determinata espressione. (Questo vale anche in ReplaceAll e ReplaceRepeated Contexts, ma lo gestiscono in modo molto diverso). La priorità è generalmente intesa per corrispondere alla specificità del modello. Data un'espressione a[q][b[c,d],e[f,g]] da valutare, con la testa e gli argomenti valutati tutti completamente come saranno (vedi sotto TODO), iniziare cercando regole codificate con b che si applicano; quindi le regole contrassegnate con e ; quindi regole contrassegnate con a . All'interno di ciascuna serie di regole, viene mantenuto un ordine su quelli associati a un determinato simbolo. Le regole senza spazi (come f[a,b]=3 ) vengono posizionate automaticamente in alto e ordinate in ordine canonico (l'ordine di Ordina). Ogni volta che viene aggiunta una nuova regola, il kernel passerà attraverso la lista; se alcune regole hanno esattamente lo stesso LHS, vengono sostituite sul posto. Altrimenti, fa un confronto di specificità. Se una regola X già presente nell'elenco è determinata per essere "meno specifica" della nuova regola Y, allora Y viene posto immediatamente prima di X. Altrimenti, continua attraverso l'elenco. Se nessuna regola è meno specifica, la regola viene posizionata alla fine dell'elenco. Il controllo della specificità è più complicato e dato in maggior dettaglio nella sezione seguente.

Specificità della regola

* Se due espressioni hanno alcuna istanza di BlankSequence ( __ ), BlankNullSequence ( ___ ), opzionale ( : ), Alternatives ( | ), ripetuta ( .. ), RepeatedNull ( ... ), o argomenti opzionali ( _. ), Poi possono essere confrontati strutturalmente. Dati due alberi di espressioni equivalenti X e Y, dove tutti gli spazi vuoti in Y sono vuoti anche in X, ma X ha spazi vuoti dove Y non lo fa, allora Y è più specifico. * Se due espressioni sono equivalenti tranne che alcune istanze di _ sono state sostituite con __ nell'altra espressione, o __ sono state sostituite con ___ , allora la prima è più specifica. * Se strippaggio un altro opzionale ( : ) (o facoltativo _. ) Termini dà l'altra espressione, poi il secondo è più specifico. * Se un certo insieme di scelte da Alternative dà l'altra espressione, allora quest'ultimo è più specifico. * Se si sostituiscono tutte le istanze di RepeatedNull[foo] con Repeated[foo] , o Repeated[foo] con foo , dà l'altra espressione, quest'ultima è più specifica * Alcune combinazioni di queste regole possono essere applicate contemporaneamente, ma non è attualmente sapere quali sono i casi per questo. * Combinazioni di espressioni come _List e {___} teoricamente dovrebbero trattarle in modo identico, ma il confronto sembra essere stranamente dipendente dal contesto, occasionalmente classificandole in un modo o nell'altro.

Blocca il contesto

Un contesto di blocco è più restrittivo, in quanto l'LHS di una regola in un blocco può essere solo un simbolo. Cioè, solo le definizioni della forma f=2+x , non f[x_]=2+x . (Si noti che, da un punto di vista pratico, le funzioni possono ancora essere costruite con definizioni come `Set [Blocco è correlato al suo contesto genitore in quanto qualsiasi nuova definizione durante la valutazione del Blocco viene inoltrata al contesto circondato come normale, ma "ombreggia" alcune serie di variabili, fornendo definizioni che possono nascondere quelle del contesto circostante.Le definizioni dal contesto circostante sono ancora accessibili durante la valutazione dell'espressione interna, poiché non può esserci definizione associata a un simbolo, non c'è nozione di priorità come sopra.

Contesto abbinato

Dopo che una regola è stata abbinata, ci sono definizioni associate localmente per le variabili. Questo si verifica in modo lessicale . Vale a dire, si susseguono nelle definizioni vincolate per le variabili nell'espressione, senza valutare qualcos'altro. Solo dopo che tutte le sostituzioni si sono verificate, inizia a valutare l'espressione, nel suo insieme, di nuovo dall'alto. Il modo principale in cui vengono creati contesti corrispondenti è una regola di un contesto o regola impostato. Ad esempio, in

g[a_]:=a+x;
f[x_]:=x+g[1];
f[x^2]
(*Yields 1+x+x^2 *)

Quando si abbina la regola f[x_] a f[y] , il simbolo x è associato al valore x^2 . Esegue l'unica sostituzione, ma poiché non valuta g , restituisce x^2+g[1] . Questo viene quindi valutato nuovamente nel Set Context circostante e diventa 1+x+x^2 . La differenza significativa nella valutazione in un contesto corrispondente è che la sostituzione non è ricorsiva. Quando si sostituisce x->x^2 , non si ripete nemmeno sui propri risultati.

In particolare, i contesti corrispondenti vengono creati da With , Module , Function e Replace . Molte altre funzioni li creano internamente, ad esempio, Plot utilizza questo tipo di contesto per valutare l'espressione da tracciare.

Sostituisci contesto ripetuto

Un ContextRepeated Context viene creato quando si verifica una qualsiasi applicazione di ReplaceRepeated . Questo è distinto dal fatto che può avere qualsiasi espressione come regola LHS, compresi quelli senza tag, come _[_] . In questo senso è il contesto più flessibile. Può anche includere diverse regole che possono essere in conflitto, quindi deve mantenere una priorità. Un contesto ReplaceRepeated applicherà prima la prima regola nell'elenco, laddove applicabile. Se non riesce a corrispondere, procede al secondo e così via. Se in qualsiasi momento una regola corrisponde, ritorna alla prima regola e ricomincia. Se in qualsiasi momento si verifica un'applicazione di regole e non si verifica alcuna modifica, verrà interrotta, anche se altre regole successive nell'elenco apporterebbero una modifica. Ciò significa che eventuali regole meno specifiche in precedenza nell'elenco impediranno l'utilizzo di regole successive. Inoltre, posizionando a_->a nella parte anteriore dell'elenco di regole si causerà la chiusura immediata dell'intero ReplaceRepeated .

Sostituisci tutto il contesto

Un ContextAll Context viene creato quando si verifica una qualsiasi applicazione di ReplaceAll . Il suo funzionamento è simile a quello di ReplaceRepeated in quanto la sua priorità dell'applicazione delle regole va in ordine nell'elenco quando due possono essere applicate allo stesso livello dell'espressione. Tuttavia, è come un contesto abbinato in quanto i contenuti sostituiti non vengono ulteriormente valutati, nemmeno da regole successive . Ad esempio x/.{x->y,y->z} produce y . Pertanto non è corretto visualizzare un'applicazione di ReplaceAll che applica a turno ciascuna regola. Invece, attraversa l'albero, cercando le regole applicabili. Quando trova qualcosa che corrisponde, esegue la sostituzione, quindi ritorna all'albero, senza attraversare il nuovo albero. Vale anche la pena notare che tenta di applicare le regole dall'alto verso il basso, risultando, di conseguenza, fuori dalla lista. Per esempio,

Cos[1 + 2 Sqrt[Sin[x]]] /. {Cos[_] -> 5, Sin[_] :> (Print[1]; 10)}
Cos[1 + 2 Sqrt[Sin[x]]] /. {Sin[_] :> (Print[1]; 10), Cos[_] -> 5}

entrambi producono 5 senza stampare nulla. Poiché Cos[_] corrisponde a un livello più alto dell'albero, lo applica per primo.

Hold e Evaluate e l'ordine di esecuzione

L'ordine di valutazione, data un'espressione, procede come HoldFirst : * Valutare il capo nel modo più completo possibile * Se la testa ha una proprietà Hold ( HoldFirst , HoldRest , HoldAll , HoldAllComplete ), quindi * Controllare gli argomenti rilevanti. A meno che non sia HoldAllComplete , controlla se la testa è Evaluate . Se lo è, quindi rimuovere la Evaluate e contrassegnarlo per essere valutato comunque. * Controllare gli argomenti per le istanze di Non Unevaluated e spogliarli se necessario, a meno che non sia presente la proprietà HoldAllComplete . * Appiattisci gli argomenti dalla Sequence s, a meno che non venga applicato SequenceHold . * Applicare gli attributi Flat , Listable , Orderless come applicabile. * Applica la valutazione associata agli upvalues ​​dell'argomento (i loro Tag) * Applica la valutazione associata alla testa.

Quando la valutazione di un'espressione è completa, viene contrassegnata come valutata completamente. Le valutazioni successive che hanno colpito quell'espressione non cercheranno di valutarla. Se una nuova regola è definita su un simbolo che si trova all'interno, la bandiera viene rimossa e può essere valutata di nuovo. Il luogo notevole in cui questo 'fallisce' è con Condition ( \; ): una regola condizionale potrebbe non applicarsi alla valutazione iniziale. Se un simbolo non correlato modifica i valori e ora la condizione è applicabile, l'espressione è ancora contrassegnata come valutata completamente e non cambierà di conseguenza. La funzione Update è unica nel senso che valuterà il suo argomento indipendentemente dal suo stato già valutato o meno, forzando un "lavaggio della cache" di sorta.

Ci sono una serie di altre funzioni che sono spesso considerati come eccezionali, tale Hold , Defer , ReplacePart , Extract , o ReleaseHold . Questi effetti possono essere tutti raggiunti tramite attributi (come HoldAll ) e la normale definizione delle funzioni e non devono essere gestiti in modo univoco dal valutatore.

Applicazione di `ReplaceAll` e` ReplaceRepeated`

Esempio di come ReplaceAll applica solo una regola al massimo una volta, mentre ReplaceRepeated lo farà in un ciclo, ma riavvia sempre l'applicazione dalla prima regola.

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" *)

Bubble sort

Ordinamento delle bolle con regole e sostituzioni:

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}
*)


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow