It seems that I have solved the problem. Here is the function:
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]
And I just have got the answer to the question on InString
in MathLink
mode from Todd Gayley (Wolfram Research):
InString is only assigned when using
EnterTextPacket, not
EnterExpressionPacket. There is no
string form of the input when sending
EnterExpressionPacket (whose content
is, by definition, already an
expression).
EDIT:
I just have found that my code does not work with input expressions with head Evaluate
. The solution is to replace HoldForm
by HoldComplete
in my code:
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]]
This works well. Another approach would be to unprotect HoldForm
and set up attribute HoldAllComplete
on it. I'm wondering why HoldForm
does not have this attribute by default?
EDIT 2:
In the comments for the main question Leonid Shifrin suggested much better solution:
getLastInput :=
Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
With[{line=$Line-1},HoldComplete[In[line]]/.DownValues[In]]]
See comments for details.
EDIT 3:
The last code can be made even better for by replacing HoldComplete
by double HoldForm
:
getLastInput :=
Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
With[{line=$Line-1},HoldForm@HoldForm[In[line]]/.DownValues[In]]]
The idea is taken from presentation by Robby Villegas of Wolfram Research at the 1999 Developer Conference. See subsection "HoldCompleteForm: a non-printing variant of HoldComplete (just as HoldForm is to Hold)" in "Working With Unevaluated Expressions" notebook posted here.
RuleDelayed
. But the culprit is likelyRuleDelayed
itself, not the absence ofHoldAllComplete
attribute. Rather, you can use the latter to get what you want, but that's not the only way. For example,Block[{RuleDelayed = Hold}, DownValues[In]]
will show the original form as well. Normally,Unevaluated
wrappers should be restored if no evaluation took place. Apparently,RuleDelayed
violates this, e.g.a :> Unevaluated[b]
. For other wrappers with just normalHoldAll
,Unevaluated
is restored. – BartolomeoBlock
. Is there a way to make the code shorter? – InofficiousBlock
seems the only way to go. I wasn't suggesting a new method in my comment. I was just pointing out that the problem is not in the absence ofHoldAllComplete
, but in the peculiarities of the implementation ofRuleDelayed
, which go at odds with the standard evaluation sequence. The distinction may not play a role here, but IMO is important for anyone who wants a detailed and correct understanding of various aspects of evaluation (frankly, I was puzzled for a while. For me, this was important to understand, may be some other people will find it interesting too). – BartolomeoClear[getLastInput]; getLastInput := #[[Position[#[[All, 1]], _?(! FreeQ[#, $Line - 1] &), 1, 1][[1, 1]], 2]] &@ Block[{RuleDelayed = Hold}, DownValues[In]]
– BartolomeoUnevaluated
is restored." IsUnevaluated
restored or just leaved unchanged? And about you code above. Try to evaluategetLastInput
twice after defining it. The first time it shows nothing, the second generates error. – InofficiousHoldForm
. Try any of these, should work:getLastInput := First@Extract[ Extract[#, Position[#[[All, 1]], _?(! FreeQ[#, $Line - 1] &), 1, 1][[1, 1]]], {{2}}, HoldForm] &@ Block[{RuleDelayed = Hold}, DownValues[In]]
orgetLastInput := With[{line = $Line - 1, myHold = Unique["hold", {HoldAll}]}, HoldForm[ In[line]] /. (Block[{RuleDelayed = myHold}, Map[HoldForm, DownValues[In], {2}]] /. myHold -> RuleDelayed)]
. Both are a bit longer than my first suggestion, but neither usesHoldComplete
, which was my main point – BartolomeoUnevaluated
being stripped off/ restored, you won't find this in the documentation, but search for old WRI technical report by David Withoff named "Mathematica internals" - it is there, along with some other interesting details. It should be freely available on the web. – BartolomeoHoldComplete
andRuleDelayed
:getLastInput := With[{line = $Line - 1}, HoldForm[In[line]] /. Block[{RuleDelayed}, SetAttributes[RuleDelayed, HoldAll]; Map[HoldForm, DownValues[In], {2}]]]
– BartolomeoHoldForm[x] /. Block[{RuleDelayed}, SetAttributes[RuleDelayed, HoldAll]; x :> Unevaluated[1 + 1]]
(I meanUnevaluated
is removed)? And I should point out that all your functions cannot work with inputs withEvaluate
head. – InofficiousBlock
before the rule is applied, soRuleDelayed
gets a chance to removeUnevaluated
(just as if you'd use it directly). RegardingEvaluate
- true, for this you needHoldComplete
(changeHoldForm
toHoldComplete
everywhere in my code, and alsoHoldAll
toHoldAllComplete
inSetAttributes
). But here we useHoldComplete
to solve a different problem, namely, deal with explicitEvaluate
entered at the top-level. – BartolomeoBlock
RuleDelayed
completely, in the sense that it will still do replacements (perhaps, it is not aboutRuleDelayed
but about replacement operators). Anyways, we can use this to our advantage, to produce even more elegant solution:getLastInput := Block[{RuleDelayed}, SetAttributes[RuleDelayed, HoldAll]; With[{line = $Line - 1}, HoldForm[In[line]] /. DownValues[In]]]
. The same remark here - replaceHoldForm
withHoldComplete
andHoldAll
withHoldAllComplete
to deal withEvaluate
. – BartolomeoHoldComplete
to get it right. Here is an illustration (try it withHoldForm
- basedgetLastInput
):Clear[a]; a /: f_[l_, a] := f[l, 1]; a getLastInput
(again, all statements on separate lines. There should be 4 lines here in this example, witha
occupying a separate line) – BartolomeogetLastInput
function is just brilliant! The only sad thing is that such things probably will never be officially documented because they breaks the official slogan of "deeply integrated system". – InofficiousRuleDelayed
. It indeed contradicts somewhat the phrase in the documentation thatRuleDelayed
"does not evaluate its r.h.s". But, so to say, the exceptions are "of the measure zero". It would be a documentation problem for any industrial system which exposes its internals to the end user (who then can do almost as much as a developer). I personally quite like the latter approach and consider such cases as a necessary evil - the price for power. – Bartolomeo