Dr *_*Joe 5 wolfram-mathematica mathematica-frontend
我有一些应该是不可交换的符号,但我不想在构造方程时记住哪些表达式具有这种行为。
我曾想过使用 MakeExpression 作用于原始框,并在适当时自动将乘法提升为非交换乘法(例如,当某些符号是非交换对象时)。
我想知道是否有人有过这种配置的经验。
这是我到目前为止所得到的:
(* Detect whether a set of row boxes represents a multiplication *)
Clear[isRowBoxMultiply];
isRowBoxMultiply[x_RowBox] := (Print["rowbox: ", x];
Head[ToExpression[x]] === Times)
isRowBoxMultiply[x___] := (Print["non-rowbox: ", x]; False)
(* Hook into the expression maker, so that we can capture any \
expression of the form F[x___], to see how it is composed of boxes, \
and return true or false on that basis *)
MakeExpression[
RowBox[List["F", "[", x___, "]"]], _] := (HoldComplete[
isRowBoxMultiply[x]])
(* Test a number of expressions to see whether they are automatically \
detected as multiplies or not. *)
F[a]
F[a b]
F[a*b]
F[a - b]
F[3 x]
F[x^2]
F[e f*g ** h*i j]
Clear[MakeExpression]
Run Code Online (Sandbox Code Playgroud)
这似乎可以正确识别乘法语句的表达式:
During evaluation of In[561]:= non-rowbox: a
Out[565]= False
During evaluation of In[561]:= rowbox: RowBox[{a,b}]
Out[566]= True
During evaluation of In[561]:= rowbox: RowBox[{a,*,b}]
Out[567]= True
During evaluation of In[561]:= rowbox: RowBox[{a,-,b}]
Out[568]= False
During evaluation of In[561]:= rowbox: RowBox[{3,x}]
Out[569]= True
During evaluation of In[561]:= non-rowbox: SuperscriptBox[x,2]
Out[570]= False
During evaluation of In[561]:= rowbox: RowBox[{e,f,*,RowBox[{g,**,h}],*,i,j}]
Out[571]= True
Run Code Online (Sandbox Code Playgroud)
因此,看起来我可以有条件地重写底层表达式的框,这并不是不可能的;但如何可靠地做到这一点呢?
以表达式 为例RowBox[{"e","f","*",RowBox[{"g","**","h"}],"*","i","j"}],这需要重写,因为RowBox[{"e","**","f","**",RowBox[{"g","**","h"}],"**","i","**","j"}]这对于模式匹配器和规则集来说似乎是一个不平凡的操作。
对于那些对我更有经验的人的任何建议,我将不胜感激。
我试图找到一种方法来做到这一点而不改变默认行为和乘法顺序。
谢谢!:)
乔
这不是对您的问题最直接的答案,但对于许多目的来说,直接使用盒子进行低级工作可能是一种矫枉过正。这是一种替代方法:让 Mathematica 解析器解析您的代码,然后进行更改。这是一种可能性:
ClearAll[withNoncommutativeMultiply];
SetAttributes[withNoncommutativeMultiply, HoldAll];
withNoncommutativeMultiply[code_] :=
Internal`InheritedBlock[{Times},
Unprotect[Times];
Times = NonCommutativeMultiply;
Protect[Times];
code];
Run Code Online (Sandbox Code Playgroud)
这会Times动态替换NonCommutativeMultiply, 并避免您提到的复杂性。通过使用 Internal`InheritedBlock,我Times对内部执行的代码进行了本地修改withNoncommutativeMultiply。
您现在可以使用以下命令自动应用此功能$Pre:
$Pre = withNoncommutativeMultiply;
Run Code Online (Sandbox Code Playgroud)
现在,例如:
In[36]:=
F[a]
F[a b]
F[a*b]
F[a-b]
F[3 x]
F[x^2]
F[e f*g**h*i j]
Out[36]= F[a]
Out[37]= F[a**b]
Out[38]= F[a**b]
Out[39]= F[a+(-1)**b]
Out[40]= F[3**x]
Out[41]= F[x^2]
Out[42]= F[e**f**g**h**i**j]
Run Code Online (Sandbox Code Playgroud)
当然,$Pre以这种方式使用几乎不合适,因为在所有代码中,乘法将被非交换乘法取代 - 我用它作为说明。您可以对 进行更复杂的重新定义Times,这样这只适用于某些符号。
这是基于词法而不是动态范围的更安全的替代方案:
ClearAll[withNoncommutativeMultiplyLex];
SetAttributes[withNoncommutativeMultiplyLex, HoldAll];
withNoncommutativeMultiplyLex[code_] :=
With @@ Append[
Hold[{Times = NonCommutativeMultiply}],
Unevaluated[code]]
Run Code Online (Sandbox Code Playgroud)
您可以以相同的方式使用它,但只有Times代码中明确存在的那些实例才会被替换。同样,这只是原则的说明,人们可以根据需要扩展或专门化它。With人们可以使用具有相似语义的替换规则,而不是在专门化/添加特殊情况的能力方面相当有限的 。
| 归档时间: |
|
| 查看次数: |
1413 次 |
| 最近记录: |