Evaluiere über eine Ebene innerhalb von Hold in Mathematica

8

Die Mathematica-Dokumentation zu Evaluate bei möglichen Problemen sagt:

  

Evaluate funktioniert nur beim ersten   Ebene, direkt in einer gehaltenen Funktion

Warum hat Mathematica diese Einschränkung? Also, wenn ich einen Ausdruck mit mehr als einer Ebene habe, nehmen Sie dieses vereinfachte Beispiel:

Halten Sie [Plus [Plus [2, 2], 2]]]

gedrückt

Nun nehme ich an, ich möchte sehen, was die Antwort für das zweite Plus ist, ohne irgendetwas auf Ebenen darunter zu bewerten. Ich habe verschiedene Dinge ausprobiert, wie zum Beispiel:

%Vor%

Beim ersten Halten wird in diesem Fall alles über die erste Stufe hinaus unbewertet. Das Ziel besteht darin, die Auswertung eines Ausdrucks auf jeder Stufe von der innersten verschachtelten Funktion zur äußeren zu steuern, indem die aufeinanderfolgenden Hold-, ReleaseHold- und Evaluate-Funktionen verwendet werden, um dies zu erreichen. Ich weiß, dass ich Trace verwenden kann, um zu sehen, was jenseits von Level 1 in einem Ausdruck passiert, aber das ist anders und manchmal komplex, um mit längeren Ausdrücken zu lesen.

Es scheint, als ob die einzige Möglichkeit darin besteht, den Ausdruck in Extract, Part oder Level zu extrahieren und vollständig zu demontieren; evaluiere einen Teil des Ausdrucks, den ich möchte; Dann rekonstruiere und ordne den Ausdruck für jede Stufe wieder zusammen. Gibt es andere Ansätze oder Funktionen, um dies zu erreichen, könnte ich in Betracht ziehen?

Edit: Dies könnte ein besseres Beispiel sein, um den Ansatz der Freigabe des ersten Hold zu betrachten. Mit dem Ausdruck:

%Vor%

Wenn Sie den ersten Hold loslassen und einen höheren Level in einem Ausdruck beim dritten Plus halten, um so zu sehen:

%Vor%

Sie werden feststellen, dass Mathematica niedrigere Ebenen im Hintergrund auswertet, wenn Sie wirklich warten möchten.

    
dbjohn 28.06.2010, 22:28
quelle

4 Antworten

3

Ich kann nicht den genauen Grund angeben, warum Evaluate "nur auf der ersten Ebene arbeitet, direkt in einer gehaltenen Funktion", aber ich vermute, dass es teilweise effizient ist, da es langsam wäre, wenn der Evaluator das komplette scannen müsste Ausdrucksbaum von gehaltenen Argumenten, die an eine Funktion mit einem Hold* -Attribut für verschachtelte Evaluate -Ausdrücke übergeben und ausgewertet werden, und dann recurse und nach Evaluate Teilausdrücken in dem gerade evaluierten Zustand suchen, während der Rest des Ausdrucks unbewertet bleibt vor allem, wenn das nicht immer das ist, was du sowieso willst.

Das, was Sie wollen, ist ziemlich einfach mit einer Kombination von Extract und ReplacePart though:

%Vor%

Damit können wir einen weiteren Grund illustrieren, warum es nicht sinnvoll ist, dass Evaluate auf irgendeiner Ebene in einem Ausdruck arbeitet, der als Argument an eine Funktion mit einem Hold* -Attribut übergeben wurde, unter Berücksichtigung des folgenden Ausdrucks mit i :

%Vor%

Beachten Sie, dass der Wert von j 4 wäre, wenn wir den ersten Teil dieses Ausdrucks vor dem Plus ausgewertet hätten, aber die Ergebnisse sind unterschiedlich, da wir nur eine Teilbewertung durchführen und i=2 wurde nicht ausgewertet, als wir die Teilausdruck-Einstellung j ausgewertet haben. Manchmal ist dies möglicherweise das, was Sie wollen, aber oft ist es sehr wahrscheinlich nicht.

Beachten Sie, dass sogar Evaluate in der ersten Ebene von einer Funktion mit dem Attribut HoldAllComplete oder mit HoldComplete :

besiegt werden kann %Vor%

... versus:

%Vor%

Schließlich kann die Ausgabe von Trace ein wenig dicht sein, aber Sie können herausfiltern, was Sie wollen, indem Sie Muster oder Symbole von Interesse im zweiten Argument verwenden:

%Vor%

HTH!

    
Michael Pilat 29.06.2010, 01:17
quelle
3

Wie so oft, wenn Sie in Mathematica etwas Schwieriges tun wollen, kommen Mustererkennung und Regelersetzung zur Rettung. In diesem Fall müssen Sie jedoch etwas Seltsames tun, und Sie haben um Replace anstelle von ReplaceAll (den Operator /. ) zu verwenden, damit Sie das optionale dritte Argument nutzen können, um ihm eine Level-Spezifikation zu geben. Verwenden Sie das von Ihnen angebotene Beispiel:

%Vor%

Das nutzlos aussehende

%Vor%

Regel ist eigentlich ein dokumentierter Weg , um lokale Variablen zwischen der Testmatch und dem Körper des zu teilen With Struktur; Hier machen Sie nichts mit der lokalen Variablen, sondern erzwingen ihre Auswertung auf Umwegen --- weil weniger Umwege nicht funktionieren!

BEARBEITEN, um hinzuzufügen: Ich denke, dass du das Ergebnis von Level falsch interpretierst; Die beiden Ausdrücke auf der Ebene {2} dieses Ausdrucks sind 2 und Plus[2, 2] ; Sie können dies sehen, indem Sie das optionale dritte Argument für level verwenden, das dem optionalen dritten Argument von Extract ähnlich ist:

%Vor%

Mit der {2} Level-Spezifikation wird Replace versuchen, die Regel mit diesen beiden Ausdrücken abzugleichen und zu ersetzen, und sie wird mit der zweiten funktionieren.

    
Pillsy 01.07.2010 14:14
quelle
2

Eine Methode, bei der Extract nicht involviert ist, besteht darin, die Teile innerhalb von Hold in innere Hold s zu wickeln und dann die äußere Hold :

freizugeben %Vor%

Sie können verschiedene Spiele in dieser Richtung spielen, aber da ich nicht sagen kann, was Sie machen wollen, ist es etwas schwierig, etwas Bestimmtes zu sagen. Etwas, das nützlich sein könnte, ist, Ihre eigene Hold zu definieren, die absteigt, wie Sie wollen:

%Vor%

Beachten Sie, dass dieser sich dem äußeren Hold s nähert, sobald die Innenseiten umschlossen sind, so dass beispielsweise die Ebenheit von Plus eintritt:

%Vor%     
Janus 29.06.2010 14:00
quelle
2

Die Idee zu ReplacePart und Extract funktioniert von Antwort von Michael Pilat kann man HoldAndEvaluate function schreiben, was erlaubt Er kann einen gewünschten Teil des Ausdrucks auswerten, ohne seine Position berechnen zu müssen (er kann mit "MyEvaluate" markiert werden).

%Vor%     
fiktor 24.01.2011 14:18
quelle

Tags und Links