Кажется, я решил проблему.Вот функция:
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]
И я только что получил ответ на вопрос о InString
в режиме MathLink
от Тодда Гейли (Wolfram Research):
InString назначается только при использовании EnterTextPacket, а не EnterExpressionPacket.При отправке EnterExpressionPacket отсутствует строковая форма ввода (содержимое которого по определению уже является выражением).
РЕДАКТИРОВАТЬ:
У меня просто естьобнаружил, что мой код не работает с входными выражениями с головой 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:
В комментариях к основному вопросу Леонид Шифрин предложил гораздо лучшее решение:
getLastInput :=
Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
With[{line=$Line-1},HoldComplete[In[line]]/.DownValues[In]]]
Подробнее см. В комментариях.
РЕДАКТИРОВАТЬ 3: Последний код можно сделать еще лучше, заменив HoldComplete
на двойной HoldForm
:
getLastInput :=
Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
With[{line=$Line-1},HoldForm@HoldForm[In[line]]/.DownValues[In]]]
Идея взята из презентации Робби Виллегаса из Wolfram Research на конференции разработчиков 1999 года.См. Подраздел «HoldCompleteForm: вариант« HoldComplete »без печати»