模拟MakeBoxes
的最简单方法是什么,它只会在其行为方面重现:将仅包含FormatValues
的符号的正确表达式转换为BoxForms
:
Trace[MakeBoxes[graphics[disk[]], StandardForm], TraceInternal -> True]
此函数应该是递归的MakeBoxes
。真正令人困惑的是如何将disk[]
转换为RowBox[{"disk", "[", "]"}]
,避免解析原始表达式的字符串表示。
P.S。这个问题来自previous question。
答案 0 :(得分:2)
我认为你不能以这种或那种方式避免解析或字符串转换 - 最后你需要字符串,并且你从符号开始。要么你以某种方式reuse MakeBoxes
,要么你必须处理字符串。拖动我的代码:以下简单的框制作功能基于发布的here Mathematica解析器(我的第二篇文章位于页面底部):
Clear[toBoxes];
toBoxes[expr_] :=
First[parse[tokenize[ToString@FullForm[expr]]] //. {
head_String[elem_] :> RowBox[{head, "[", elem, "]"}],
head_String[elems___] :> RowBox[{head, "[", RowBox[Riffle[{elems}, ","]], "]"}]}]
如果您不想解析但不介意ToString
,那么上述内容略有不同:
toBoxesAlt[expr_] :=
expr /. s_Symbol :> ToString[s] //. {
head_String[elem_] :> RowBox[{head, "[", elem, "]"}],
head_String[elems___] :> RowBox[{head, "[", RowBox[Riffle[{elems}, ","]], "]"}]}
请注意,最后一个函数不涉及任何解析。然后,我们需要:
Clear[MakeBoxesStopAlt];
MakeBoxesStopAlt /: MakeBoxes[MakeBoxesStopAlt[expr_], form_] := toBoxes[expr]
例如:
In[327]:= MakeBoxesStopAlt[Graphics[Disk[]]]
Out[327]= Graphics[Disk[List[0, 0]]]
如果我的实现看起来太复杂,你可能想要重新实现解析器,尽管我的效率很高。
修改强>
这是一种非常简单且可能很慢的解析方法:函数tokenize
与以前相同,为方便起见,我将在此重新发布:
tokenize[code_String] :=
Module[{n = 0, tokenrules},
tokenrules = {"[" :> {"Open", ++n}, "]" :> {"Close", n--},
Whitespace | "" ~~ "," ~~ Whitespace | ""};
DeleteCases[StringSplit[code, tokenrules], "", Infinity]];
这是解析功能:
parseSimple[tokenized_] :=
First[tokenized //. {left___,
Shortest[
PatternSequence[h_, {"Open", n_}, elems___, {"Close", n_}]], right___} :>
{left, h[elems], right}];
您可以使用它代替parse
,然后这两个函数构成解析器的自包含解决方案。
与我对上一个问题的回答相同的注释是:如果您想要处理/禁止表达式评估,请在需要时添加适当的属性和Unevaluated
包装。
<强> EDIT2 强>
这是一个版本的makeBoxes,它不涉及解析,不会泄漏评估并且能够正确处理嵌套头(至少对于一些简单的测试):
Clear[handleElems];
handleElems[] := Sequence[];
handleElems[el_] := el;
handleElems[els__] := RowBox[Riffle[{els}, ","]];
ClearAll[makeBoxes];
SetAttributes[makeBoxes, HoldAllComplete];
makeBoxes[ex_] :=
Block[{makeBoxes},
SetAttributes[makeBoxes, HoldAllComplete];
makeBoxes[expr_ /;!FreeQ[Unevaluated[expr],
s_ /; AtomQ[Unevaluated[s]] && ! StringQ[Unevaluated[s]]]] :=
makeBoxes[#] &@(Unevaluated[expr] /.
s_ /; AtomQ[Unevaluated[s] && ! StringQ[Unevaluated[s]]] :>
ToString[Unevaluated[s]]);
makeBoxes[a_ /; AtomQ[Unevaluated[a]]] := a;
makeBoxes[expr_] /; MatchQ[expr, h_String[___]] :=
expr //. {
(h : ("Rule" | "RuleDelayed"))[l_, r_] :>
RowBox[{l, h /. {
"Rule" -> "\[Rule]",
"RuleDelayed" -> "\[RuleDelayed]"
}, r}],
"List"[elems___] :> RowBox[{"{", handleElems[elems], "}"}],
head_String[elems___] :> RowBox[{head, "[", handleElems[elems], "]"}]
};
makeBoxes[expr_] :=
RowBox[{makeBoxes[#] &@Head[expr], "[",
handleElems @@ (makeBoxes @@@ expr), "]"}];
makeBoxes @@ (HoldComplete[ex] /. s_String :>
With[{eval = StringJoin["\"", s, "\""]}, eval /; True])
];
使用示例:
In[228]:= a=1;b=2;c = 3;
In[229]:= makeBoxes[a:>b]
Out[229]= RowBox[{a,:>,b}]
In[230]:= makeBoxes[a->b]
Out[230]= RowBox[{a,->,b}]
In[231]:= makeBoxes[{a,{b,c}}]
Out[231]= RowBox[{{,RowBox[{a,,,RowBox[{{,RowBox[{b,,,c}],}}]}],}}]
In[232]:= makeBoxes[a[b][c]]
Out[232]= RowBox[{RowBox[{a,[,b,]}],[,c,]}]
In[233]:= makeBoxes[a[b[e[],f[]],c[g[],h[]]][x,y]]
Out[233]= RowBox[{RowBox[{a,[,RowBox[{RowBox[{b,[,RowBox[{RowBox[{e,
[,]}],,,RowBox[{f,[,]}]}],]}],,,RowBox[{c,[,RowBox[{RowBox[{g,[,]}],,,
RowBox[{h,[,]}]}],]}]}],]}],[,RowBox[{x,,,y}],]}]
在所有测试的案例中,输出与MakeBoxes
的输出相同。
答案 1 :(得分:0)
以下是我对简化MakeBoxes
的实现,而没有将原始表达式转换为字符串:
ClearAll[SimpleMakeBoxes, SimpleMakeBoxesRules];
SetAttributes[SimpleMakeBoxes, HoldAll];
SimpleMakeBoxesRules = {h_Symbol[] :> RowBox[{ToString@h, "[", "]"}],
h_Symbol[expr_] :>
RowBox[{ToString@h, "[", Unevaluated[expr] /. SimpleMakeBoxesRules, "]"}],
h_Symbol[expr__] :>
RowBox[{ToString@h, "[",
RowBox[Riffle[
List @@ Replace[Hold[expr],
x_ :> (Unevaluated[x] /. SimpleMakeBoxesRules), {1}], ","]], "]"}],
a:(_Real | _Integer | _String) :> ToString[FullForm@a]};
SimpleMakeBoxes[expr_] :=
Unevaluated[expr] /.
SimpleMakeBoxesRules //. {RowBox[{"List", "[", elems___, "]"}] :>
RowBox[{"{", elems, "}"}],
RowBox[{"Rule", "[", RowBox[{lhs_, ",", rhs_}], "]"}] :>
RowBox[{lhs, "\[Rule]", rhs}],
RowBox[{"RuleDelayed", "[", RowBox[{lhs_, ",", rhs_}], "]"}] :>
RowBox[{lhs, "\[RuleDelayed]", rhs}]}
用法示例:
In[7]:= SimpleMakeBoxes@Graphics[Disk[]]
RawBoxes@%
Out[7]= RowBox[{Graphics,[,RowBox[{Disk,[,]}],]}]
Out[8]= Graphics[Disk[]]