5

我经常希望看到Mathematica的图形对象的内部表示不是在其中,FullForm而是在可读性更强InputForm的情况下,能够通过双击它来选择部分代码并轻松地将这段代码复制到新的输入Cell中。但默认情况下InputForm不允许这样做,因为InputForm默认情况下显示为 a String,而不是Mathematica的代码。有没有办法InputForm显示为Mathematica的代码?

我还经常希望看到这样的缩短版本,InputForm其中所有长的坐标列表都显示为第一个坐标,然后是用 包裹的跳过的坐标值的数量Skeleton,所有的空Lists都被删除,所有的数字也被缩短以显示不超过 6 位数字。最好仅将 6 位数字用于坐标,但用于颜色指令,例如Hue仅显示 2 个有效数字。例如,

Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, 
  Filling -> {1 -> {2}}] // ShortInputForm

应该给:

Graphics[GraphicsComplex[{{1.28228`*^-7, 1.28228*^-7}, <<1133>>}, 
    {{{EdgeForm[], Directive[{Opacity[0.2], Hue[0.67, 0.6, 0.6]}], 
          GraphicsGroup[{Polygon[{{1133, <<578>>}}]}]}, 
        {EdgeForm[], Directive[{Opacity[0.2], Hue[0.67, 0.6, 0.6]}],              
     GraphicsGroup[{Polygon[{{432, <<556>>}}]}]}}, {{Hue[0.67, 0.6, 
      0.6], Line[{1, <<431>>}]}, {Hue[0.91, 0.6, 0.6], 
          Line[{432, <<701>>}]}}}], {AspectRatio -> GoldenRatio^(-1), 
  Axes -> True, AxesOrigin -> {0, 0}, 
    Method -> {"AxesInFront" -> True}, 
  PlotRange -> {{0, 2*Pi}, {-1., 1}}, 
    PlotRangeClipping -> True, 
  PlotRangePadding -> {Scaled[0.02], Scaled[0.02]}}]

(注意-0.9999998592131705转换为-1.,1.2822827157509358*^-7转换为1.28228*^-7Hue[0.9060679774997897, 0.6, 0.6]转换为Hue[0.91, 0.6, 0.6])。

通过这种方式,我希望得到InputForm作为Mathematica代码的输出,并且还有一个ShortInputForm函数可以提供该代码的缩短版本。有谁能够帮助我?


至于问题的第一部分,我找到了一种方法来实现我想要的:

Plot[{Sin[x], .5 Sin[2 x]}, {x, 0, 2 \[Pi]}, Filling -> {1 -> {2}}] //
   InputForm // StandardForm
4

2 回答 2

8

更新

shortInputForm可以在此处找到该功能的最新版本。


原帖

这是另一个更好的解决方案(与Mathematica 5 兼容):

myInputForm[expr_] := 
 Block[{oldContexts, output, interpretation, skeleton},
  output = ToString[expr, InputForm];
  oldContexts = {$Context, $ContextPath};
  $Context = "myTemp`"; $ContextPath = {$Context};
  output = DisplayForm@ToBoxes[ToExpression[output] /.
      {myTemp`interpretation -> If[$VersionNumber >= 6,
         System`Interpretation, System`First@{#} &],
       myTemp`Row -> System`Row,
       myTemp`skeleton -> System`Skeleton,
       myTemp`sequence :> (System`Sequence @@ # &)}, StandardForm];
  {$Context, $ContextPath} = oldContexts; output]
shortInputForm[expr_] := myInputForm[expr /. {{} -> Sequence[],
    lst : {x_ /; VectorQ[x, NumberQ], y__} /;
      (MatrixQ[lst, NumberQ] && Length[lst] > 3) :>
     {x /. v : {a_, b__} /; Length[v] > 3 :>
        {a, interpretation[skeleton[Length[{b}]], sequence@{b}]},
      interpretation[skeleton[Length[{y}]], sequence@{y}]},
    lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 3 :>
     {x, interpretation[skeleton[Length[{y}]], sequence@{y}]}}]

这个怎么运作

该解决方案基于简单的想法:我们需要阻止将Graphics,Point和其他内容转换为排版表达式,以使它们以内部形式显示(作为适合输入的表达式)。令人高兴的是,如果我们这样做,StandardForm会发现结果输出只是原始表达式的格式化(二维)InputForm。这正是所需要的!

但是如何做到这一点?首先,这种转换是通过FormatValuesSymbols likeGraphics等定义的来进行的。可以通过评估以下内容Point来获得此类 s 的完整列表:Symbol

list = Symbol /@ 
  Select[DeleteCases[Names["*"], "I" | "Infinity"], 
   ToExpression[#, InputForm, 
     Function[symbol, Length[FormatValues@symbol] > 0, HoldAll]] &]

我的第一个想法就是Block所有这些Symbol(并且它有效!):

myInputForm[expr_] := 
 With[{list = list}, Block[list, RawBoxes@MakeBoxes@expr]]

但是这种方法会导致对所有这些Symbols 进行评估,并且还会对FormatValues中的所有Symbols进行评估$ContextPath。我认为应该避免。

阻止这些FormatValues的其他方法只是"System`"$ContextPath. 但它仅在这些Symbols 尚未解决到"System`"上下文时才有效。所以我们需要首先将我们的表达式转换为String,然后从 中删除"System`"上下文$ContextPath,最后将字符串转换回原始表达式。然后所有新Symbol的 s 都将与当前的$Context(和GraphicsPoint)相关联,因为它们不在 中$ContextPath。为了防止上下文阴影冲突和乱扔"Global`"上下文,我切换$Context"myTemp`"可以在必要时轻松清除的上下文。

这是如何myInputForm工作的。

现在关于shortInputForm. 这个想法不仅仅是显示一个缩短的版本,myInputForm而且还保留了选择和复制部分缩短代码到新输入单元格中的能力,并使用这个代码,因为它将是没有缩写的完整代码。在版本 6 及更高版本中,可以使用Interpretation. 为了与 6 之前的版本兼容,Mathematica我添加了一段代码,如果$VersionNumber小于 6,则删除此功能。

我在使用时遇到的唯一问题Interpretation是它没有SequenceHold属性,因此我们不能简单地SequenceInterpretation. 但是这个问题可以很容易地通过将序列包装进去List然后ApplyingSequence来避免:

System`Sequence @@ # &

请注意,我需要为我使用的所有内置Symbols 指定确切的上下文,因为在调用它们时,"System`"上下文不在$ContextPath.

这结束了我在开发这些功能时做出的非标准决定。欢迎提出建议和意见!

在此处输入图像描述

于 2011-06-03T17:22:41.837 回答
0

此刻,我得出了以下解决方案:

round[x_, n_] := (10^-n*Round[10^n*MantissaExponent[x]]) /.
   {m_, e_} :> N[m*10^e];
ShortInputForm[expr_] := ((expr /.
       {{} -> Sequence[],
        lst : {x_ /; VectorQ[x, NumberQ], y__} /;
          (MatrixQ[lst, NumberQ] && Length[lst] > 2) :>
         {x, Skeleton[Length[{y}]]},
        lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 2 :>
         {x, Skeleton[Length[{y}]]}} /.
      {exp : Except[List | Point][x__] /; 
         VectorQ[{x}, MachineNumberQ] :>
        (round[#, 2] & /@ exp), 
       x_Real /; MachineNumberQ[x] :> round[x, 6]})
    // InputForm // StandardForm)

现在:

截屏

于 2011-06-03T11:15:11.930 回答