citedOpenerView 解决方案使用Trace / TraceOriginal 生成其内容。这允许在该响应中简洁地定义show 的定义,但具有丢弃一些跟踪信息的缺点。 TraceScan 提供更多信息,因为它在每次评估的开始和结束时调用用户指定的函数。
下面定义了两个函数,它们尝试将TraceScan 信息格式化为(有点)可读的形式。
traceView2 显示评估时的每个表达式,以及导致该评估结果的子评估(“步骤”)。 “向下钻取”由OpenerView 提供。该函数生成如下所示的输出:
traceView2[(a + 1) + 2]
随着视图的深入,它会迅速从页面的右侧爬出。 traceView4 提供了一种替代视图,该视图不显示爬行行为,但代价是为任何给定评估显示更少的上下文:
选择你的毒药;)
函数的定义如下...
traceView2
ClearAll@traceView2
traceView2[expr_] :=
Module[{steps = {}, stack = {}, pre, post, show, dynamic},
pre[e_] := (stack = {steps, stack}; steps = {})
; post[e_, r_] :=
( steps = First@stack ~Join~ {show[e, HoldForm[r], steps]}
; stack = stack[[2]]
)
; SetAttributes[post, HoldAllComplete]
; show[e_, r_, steps_] :=
Grid[
steps /. {
{} -> {{"Expr ", Row[{e, " ", Style["inert", {Italic, Small}]}]}}
, _ -> { {"Expr ", e}
, {"Steps", steps /.
{ {} -> Style["no definitions apply", Italic]
, _ :> OpenerView[{Length@steps, dynamic@Column[steps]}]}
}
, {"Result", r}
}
}
, Alignment -> Left
, Frame -> All
, Background -> {{LightCyan}, None}
]
; TraceScan[pre, expr, ___, post]
; Deploy @ Pane[steps[[1]] /. dynamic -> Dynamic, ImageSize -> 10000]
]
SetAttributes[traceView2, {HoldAllComplete}]
traceView4
ClearAll@traceView4
traceView4[expr_] :=
Module[{steps = {}, stack = {}, pre, post},
pre[e_] := (stack = {steps, stack}; steps = {})
; post[e_, r_] :=
( steps = First@stack ~Join~ {{e, steps, HoldForm[r]}}
; stack = stack[[2]]
)
; SetAttributes[post, HoldAllComplete]
; TraceScan[pre, expr, ___, post]
; DynamicModule[{focus, show, substep, enter, exit}
, focus = steps
; substep[{e_, {}, _}, _] := {Null, e, Style["inert", {Italic, Small}]}
; substep[{e_, _, r_}, p_] :=
{ Button[Style["show", Small], enter[p]]
, e
, Style[Row[{"-> ", r}], Small]
}
; enter[{p_}] := PrependTo[focus, focus[[1, 2, p]]]
; exit[] := focus = Drop[focus, 1]
; show[{e_, s_, r_}] :=
Column[
{ Grid[
{ {"Expression", Column@Reverse@focus[[All, 1]]}
, { Column[
{ "Steps"
, focus /.
{ {_} :> Sequence[]
, _ :> Button["Back", exit[], ImageSize -> Automatic]
}
}
]
, Grid[MapIndexed[substep, s], Alignment -> Left]
}
, {"Result", Column@focus[[All, 3]]}
}
, Alignment -> Left, Frame -> All, Background -> {{LightCyan}}
]
}
]
; Dynamic @ show @ focus[[1]]
]
]
SetAttributes[traceView4, {HoldAllComplete}]