wolfram-mathematica - 制作简化的 MakeBox

标签 wolfram-mathematica

什么是模拟 MakeBoxes 的最简单方法,它将仅在其行为的方面进行重现:将仅涉及没有 FormatValues 的符号的正确表达式转换为 BoxForms:

Trace[MakeBoxes[graphics[disk[]], StandardForm], TraceInternal -> True]

这个函数应该像 MakeBoxes 一样是递归的。真正令人困惑的是如何将 disk[] 转换为 RowBox[{"disk", "[", "]"}] 避免解析原始的字符串表示表达。

附言本题来自previous question .

最佳答案

我认为您无法以某种方式避免解析或字符串转换 - 最后您需要字符串,而您从符号开始。要么你不知何故reuse MakeBoxes ,或者你必须处理字符串。拖动我的代码:以下简单的盒子制作功能基于发布的 Mathematica 解析器 here (我在那里的第二篇文章,在页面底部):

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,然后这两个函数形成一个独立的解析器解决方案。

与我对您之前问题的回答相同的评论是按顺序排列的:如果您想处理/禁止表达式求值,请在需要时添加适当的属性和未求值包装器。

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 的输出相同。

关于wolfram-mathematica - 制作简化的 MakeBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6536040/

相关文章:

wolfram-mathematica - 试图让 Mathematica 逼近积分

wolfram-mathematica - 在 Mathematica 中查找两个 ListPlot 的交点

wolfram-mathematica - 请解释 With、Block 和 Module 的这种行为

matlab - 有没有办法自动将结果或数据从 Matlab 导入 Mathematica?

wolfram-mathematica - Gnuplot 和 Mathematica 中的颜色图

parallel-processing - 如何在 Mathematica 8 中并行化积分

wolfram-mathematica - 更改 GraphPlot 中的边路由以避免二义性

text - 从排序的短语列表中提取频率数据

math - 使用 Manipulate 控制测量零组解。案例研究

wolfram-mathematica - 使用 Total 和阈值参数减少列表的长度