wolfram-mathematica
Utvärderingsorder
Sök…
Anmärkningar
Detta är tänkt att förklara utvärderingsordningen så otvetydigt som möjligt. Det är förmodligen mindre idealiskt som introduktion till Mathematica-körning. Det bygger på Mathematicas tutorial/Evaluation genom att förklara i vilken ordning olika regler tillämpas och förklara vilka funktioner som behandlas speciellt av utvärderingsmotorn.
Utvärderingsförhållanden
När som helst exekveras kod inom ett sammanhang. Ett sammanhang består av en uppsättning ersättningsregler (dess ordbok) och en prioritering där de bör utvärderas. Vi grupperar fem slags sammanhang med distinkt beteende och begränsningar: * Ställ in sammanhang * Blockera sammanhang * Matchat sammanhang * ErsättAllt sammanhang * Ersätt upprepad kontext
Ställ in sammanhang
Ett Set Context är det som definieras av någon uppsättning Set [] -operationer (funktionen vanligare skrivna = ). Huvudexemplet är den primära exekveringsmiljön. Dess ordbok modifieras varje gång en Set [] körs på en variabel som annars inte är omfattning. De andra fallen av Set Contexts kommer från paket. Ett paketkontext är relaterat till dess överordnade sammanhang genom att alla mönster i paketet också blir mönster inom överordnade sammanhang, med ett lämpligt prefix (en definition foo[x_]=3*x blir InnerPackageName\ foo [x _] = 3 * x ').
Set Contexts kan endast innehålla regler som har en tillhörande "Tag", en sträng som är associerad med huvudet för att identifiera regelens användbarhet snabbare. En applikation av Set[yyy_,zzz_] kommer att bestämma en tagg genom att kontrollera om yyy är en symbol. Om det är så är det taggen. Annars kontrollerar den yyy[[0]] , sedan yyy[[0,0]] och så vidare. Om det vid någon tidpunkt fastställs att detta är en symbol, tas det som taggen. Om det istället är en icke-symbolatom (som sträng, heltal, verklig ...) kommer det att kasta ett fel och ingen regel skapas.
Funktionerna UpSet (skriven ^= ) och TagSet (skriven /: / = ) (och deras kusiner UpSetDelayed och TagSetDelayed) gör det möjligt att associera en regel med en annan tagg. Det finns fortfarande begränsningen att taggen måste vara en symbol. UpSet kommer att associera det med vart och ett av argumenten i uttrycket, eller deras huvud om de är en funktion med en symbol för ett huvud. Om du till exempel ringer UpSet på f[a,b,c+d,e[f,g],5,h[i][j][k],p_] kommer den associerade skapade regeln att associeras med a , b , e , och h . Argumenten c+d , 5 och p_ har inget associerat med dem och kommer att få ett felmeddelande att visas. Uppdraget kommer fortfarande att lyckas med vart och ett av argumenten, och (som kommer att klargöras senare i utvärderingsordningen) kommer det fortfarande att fungera för nästan alla ändamål. TagSet är som UpSet, men du kan ange exakt en symbol för taggen. Symbolen måste fortfarande vara något som kan ställas in av Set eller UpSet (en symbol på toppnivån i huvudet eller argumenten). Till exempel är TagSet[f, f[a,b[c]], 2] acceptabelt och kommer att associera definitionen med f ; TagSet[a, f[a,b[c]], 2] och TagSet[b, f[a,b[c]], 2] är också godtagbara, men TagSet[c, f[a,b[c]], 2] är inte.
Regler inom ett sammanhang behöver en applikationsprioritet, eftersom det kan finnas många regler som gäller för ett visst uttryck. (Detta gäller också i ReplaceAll och ReplaceRepeated Contexts, men de hanterar det mycket annorlunda). Prioriteten är i allmänhet avsedda att motsvara de specificiteten av mönstret. Med ett uttryck a[q][b[c,d],e[f,g]] att utvärdera, med huvudet och argumenten alla utvärderade så fullständigt som de kommer (se nedan TODO), börja med att leta efter regler taggade med b som gäller; sedan regler taggade med e ; sedan regler taggade med a . Inom varje uppsättning regler upprätthålls en ordning på de som är associerade med en given symbol. Regler utan tomma ämnen (som f[a,b]=3 ) placeras automatiskt upptill och sorteras i kanonisk ordning (sorteringsordningen). Varje gång en ny regel läggs till kommer kärnan att gå igenom listan; Om någon regel har exakt samma LHS, kommer den att ersättas på plats. Annars gör det en specifik jämförelse. Om en regel X som redan finns i listan fastställs att vara "mindre specifik" än den nya regeln Y, placeras Y omedelbart före X. Annars fortsätter den genom listan. Om ingen regel är mindre specifik placeras regeln i slutet av listan. Specificitetskontrollen är mer komplicerad och ges mer detaljerat i avsnittet nedan.
Regelspecificitet
* Om två uttryck har ingen instans av BlankSequence ( __ ), BlankNullSequence ( ___ ), tillval ( : ), alternativ ( | ), upprepas ( .. ), RepeatedNull ( ... ) eller valfria argument ( _. ), Sedan de kan jämföras strukturellt. Med tanke på två ekvivalenta uttrycksträd X och Y, där alla ämnen i Y också är ämnen i X, men X har ämnen där Y inte gör det, är Y mer specifik. * Om två uttryck är ekvivalenta förutom att vissa fall av _ har ersatts med __ i det andra uttrycket, eller __ har ersatts medh ___ , är det förstnämnda mer specifikt. * Om stripp en mer Valfria ( : ) (eller valfritt _. ) Termer ger den andra uttryck, då det senare är mer specifik. * Om en viss uppsättning val från alternativ ger det andra uttrycket, är det senare mer specifikt. * Om du ersätter alla förekomster av RepeatedNull[foo] med Repeated[foo] , eller Repeated[foo] med foo , ger det andra uttrycket, är det senare mer specifikt. vet vad fallet för detta är. * Kombinationer av uttryck som _List och {___} teoretiskt bör behandla dem identiskt, men jämförelsen verkar vara konstigt kontextberoende och ibland rangordna dem på ett eller annat sätt.
Blockera kontext
Ett blockkontext är mer restriktivt eftersom LHS för en regel i ett block bara kan vara en symbol. Det vill säga endast definitioner av formen f=2+x , inte f[x_]=2+x . (Observera att praktiskt sett kan funktioner fortfarande konstrueras med definitioner som "Set [Block är relaterat till dess överordnade sammanhang i det att alla nya definitioner under utvärderingen av blocket vidarebefordras till det omgivna sammanhanget som normalt, men det kommer att "skugga" några uppsättningar med variabler, tillhandahålla definitioner som kan dölja de i det omgivande sammanhanget. Definitioner från det omgivande sammanhanget är fortfarande tillgängliga under utvärderingen av det inre uttrycket. Eftersom det bara kan definieras en definition som är associerad med en symbol, finns det ingen uppfattning med prioritet som ovan.
Matchat sammanhang
När en regel har matchats finns det lokalt bundna definitioner för variabler. Detta inträffar lexiskt . Det vill säga att det ingår i de bundna definitionerna för variabler i uttrycket utan att utvärdera något annat. Först när alla underavsnitt har inträffat börjar det utvärdera uttrycket, som en helhet, uppifrån igen. Det primära sättet Matchade kontexter skapas är en regel från en Set Context eller regel. Till exempel i
g[a_]:=a+x;
f[x_]:=x+g[1];
f[x^2]
(*Yields 1+x+x^2 *)
När man matchar f[x_] -regeln till f[y] är symbolen x bunden till värdet x^2 . Den utför en substitution, men eftersom den inte utvärderar g returnerar den x^2+g[1] . Detta utvärderas sedan i det omgivande Set Context igen och blir 1+x+x^2 . Den betydande skillnaden i utvärdering i ett matchat sammanhang är att ersättningen inte är rekursiv. När den underkastas x->x^2 upprepas den inte ens med sina egna resultat.
Matchade kontexter skapas också av With , Module , Function och Replace . Många andra funktioner skapar dem internt, till exempel använder Plot denna typ av sammanhang för att utvärdera uttrycket som ska plottas.
ReplaceRepeated Context
En ReplaceRepeated-kontext skapas när någon tillämpning av ReplaceRepeated inträffar. Detta är tydligt genom att det kan ha något uttryck som regel LHS, inklusive de utan tagg, till exempel _[_] . I detta avseende är det det mest flexibla sammanhanget. Det kan också innehålla flera regler som kan konflikt, så det måste ha en prioritering. Ett ReplaceRepeated-kontext kommer att tillämpa den första regeln i listan först där det är tillämpligt. Om den inte matchar, fortsätter den till den andra, och så vidare. Om en regel matchar någon gång, återgår den till den första regeln och börjar igen. Om någon regelapplikation någon gång inträffar och ingen ändring inträffar kommer den att avsluta - även om andra regler senare i listan skulle göra en ändring. Detta innebär att alla mindre specifika regler tidigare i listan kommer att förhindra att senare regler någonsin används. Att placera a_->a framför a_->a kommer att orsaka en omedelbar avslutning av hela ReplaceRepeated .
Ersätt allt sammanhang
Ett ReplaceAll-kontext skapas när någon tillämpning av ReplaceAll uppstår. Dess funktion liknar ReplaceRepeated genom att dess tillämpning prioriteras i ordning i listan när två båda kan tillämpa på samma nivå av uttrycket. Det är dock som ett matchat sammanhang genom att det ersatta innehållet inte utvärderas ytterligare, inte ens med senare regler . Till exempel ger x/.{x->y,y->z} y . Således är det felaktigt att se en applikation av ReplaceAll som tillämpar varje regel i sin tur. Istället korsar det trädet och letar efter tillämpliga regler. När den hittar något som matchar, kör den ersättningen och returnerar sedan upp trädet utan att korsa det nya trädet. Det är också värt att notera att det försöker tillämpa regler uppifrån och ner, vilket möjligen går ur listans ordning. Till exempel,
Cos[1 + 2 Sqrt[Sin[x]]] /. {Cos[_] -> 5, Sin[_] :> (Print[1]; 10)}
Cos[1 + 2 Sqrt[Sin[x]]] /. {Sin[_] :> (Print[1]; 10), Cos[_] -> 5}
båda ger 5 utan att skriva ut något. Eftersom Cos[_] matchar en högre nivå av trädet, tillämpar den den först.
Hold och Evaluate och exekveringsorder
Utvärderingsordningen, som ges ett uttryck, fortsätter med: * Utvärdera huvudet så noggrant som möjligt * Om huvudet har en egenskap Hold ( HoldFirst , HoldRest , HoldAll , HoldAllComplete ), sedan * Kontrollera relevanta argument. Om det inte är HoldAllComplete , kontrollera om huvudet är Evaluate . Om det är det, rensa sedan Evaluate och markera det för att utvärderas ändå. * Kontrollera argument för förekomster av Unevaluated och remsa dem vid behov, såvida inte egenskapen HoldAllComplete finns. * Platta ut argument från Sequence , såvida inte SequenceHold används. * Tillämpa attributen Flat , Listable , Orderless enligt tillämpligt. * Tillämpa utvärdering förknippad med argumentets uppvärderingar (deras taggar) * Tillämpa utvärdering i samband med huvudet.
När utvärderingen av ett uttryck är klar markeras det som fullständigt utvärderat. Efterföljande utvärderingar som träffar det uttrycket kommer inte att försöka utvärdera det. Om en ny regel definieras på en symbol som förekommer inuti, tas flaggan bort och den kan utvärderas igen. Den anmärkningsvärda platsen som detta "misslyckas" är med Condition ( \; ): en villkorad regel kan eventuellt inte tillämpas vid den första utvärderingen. Om en icke-relaterad symbol ändrar värden och nu är villkoret tillämpligt, är uttrycket fortfarande markerat fullt utvärderat och kommer inte att ändras som resultat. Funktionen Update är unik genom att den kommer att utvärdera dess argument oberoende av dess redan utvärderade status eller inte, vilket tvingar en "cache flush" av sortering.
Det finns ett antal andra funktioner som ofta betraktas som exceptionella, såsom Hold , Defer , ReplacePart , Extract eller ReleaseHold . Dessa effekter kan alla uppnås genom attribut (t.ex. HoldAll ) och normal funktionsdefinition, och behöver inte hanteras unikt av utvärderaren.
Användning av "ReplaceAll" och "ReplaceRepeated"
Exempel på hur ReplaceAll endast tillämpar en regel högst en gång, medan ReplaceRepeated gör det i en loop men startar alltid om applikationen från den första regeln.
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" *)
Bubbelsorter
Bubbelsortering med regler och ersättningar:
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}
*)