看来我已经解决了这个问题。这是功能:
In[1]:=
getLastInput := Module[{num, f},
f = Function[{u, v},
{u /. {In -> num, HoldPattern -> First}, HoldForm[v]}, HoldAllComplete];
First@Cases[
Block[{RuleDelayed = f}, DownValues[In]],
{$Line - 1, x_} -> x, {1}, 1]]
In[2]:=
Unevaluated[2+2]
getLastInput
Out[2]=
Unevaluated[2+2]
Out[3]=
Unevaluated[2+2]
我刚刚从 Todd Gayley(Wolfram Research)那里得到了关于InString
in mode 问题的答案:MathLink
InString 仅在使用 EnterTextPacket 时分配,而不是 EnterExpressionPacket。发送 EnterExpressionPacket 时没有字符串形式的输入(根据定义,其内容已经是一个表达式)。
编辑:
我刚刚发现我的代码不适用于带有 head 的输入表达式Evaluate
。解决方案是在我的代码中替换HoldForm
为:HoldComplete
getLastInput := Module[{num, f},
f = Function[{u, v},
{u /. {In -> num, HoldPattern -> First}, HoldComplete[v]}, HoldAllComplete];
First@Cases[
Block[{RuleDelayed = f}, DownValues[In]],
{$Line - 1, x_} -> x, {1}, 1]]
这很好用。另一种方法是取消保护HoldForm
并在其上设置属性HoldAllComplete
。我想知道为什么HoldForm
默认情况下没有这个属性?
编辑2:
在对主要问题的评论中,Leonid Shifrin 提出了更好的解决方案:
getLastInput :=
Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
With[{line=$Line-1},HoldComplete[In[line]]/.DownValues[In]]]
详情见评论。
编辑3:
最后一个代码可以通过替换为更好HoldComplete
的 double HoldForm
:
getLastInput :=
Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
With[{line=$Line-1},HoldForm@HoldForm[In[line]]/.DownValues[In]]]
这个想法来自 Wolfram Research 的 Robby Villegas 在 1999 年开发者大会上的演讲。请参阅此处发布的“使用未评估的表达式”笔记本中的“HoldCompleteForm:HoldComplete 的非打印变体(就像 HoldForm 一样)”小节。