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ücktNun 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.
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:
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
:
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
:
... 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:
HTH!
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:
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:
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.
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
:
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:
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:
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).
Tags und Links wolfram-mathematica