如何模拟InString []? [英] How to make an analog of InString[]?

查看:85
本文介绍了如何模拟InString []?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现发送带有EnterExpressionPacket标头的输入时InString[]MathLink模式下不起作用.因此,我需要定义自己的函数以返回上一个输入行.我开发 here 的一种方法在某些情况下不起作用:

I have discovered that InString[] does not work in MathLink mode when sending input with EnterExpressionPacket header. So I need to define my own function that returns previous input line. One way I have developed here does not work in some cases:

In[1]:= Unevaluated[2 + 2]
With[{line = $Line - 1}, HoldForm[In[line]]] /. (DownValues[In])
Out[1]= Unevaluated[2 + 2]
Out[2]= 2 + 2

这是因为RuleDelayed没有HoldAllComplete属性.添加此属性可以使此操作正常:

This is because RuleDelayed has no HoldAllComplete attribute. Adding this attribute makes this OK:

In[1]:= Unprotect[RuleDelayed];
SetAttributes[RuleDelayed, HoldAllComplete];
Protect[RuleDelayed];
Unevaluated[2 + 2]
With[{line = $Line - 1}, HoldForm[In[line]]] /. DownValues[In]

Out[4]= Unevaluated[2 + 2]

Out[5]= Unevaluated[2 + 2]

但是修改内置函数通常不是一个好主意.有更好的方法吗?

But modifying built-in functions generally is not a good idea. Is there a better way to do this?

推荐答案

看来我已经解决了问题.功能如下:

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]

Todd Gayley(Wolfram Research)以MathLink模式在MathLink模式下得到了关于InString问题的答案:

And I just have got the answer to the question on InString in MathLink mode from Todd Gayley (Wolfram Research):

仅在使用时分配InString EnterTextPacket,不是 EnterExpressionPacket.没有 发送时输入的字符串形式 EnterExpressionPacket(其内容 根据定义,已经是 表达式).

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).

我刚刚发现我的代码不适用于头部为Evaluate的输入表达式.解决方案是在我的代码中将HoldForm替换为HoldComplete:

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]]

这很好.另一种方法是取消保护HoldForm并在其上设置属性HoldAllComplete.我想知道为什么HoldForm默认不具有此属性?

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?

在对主要问题的评论中,列昂尼德·希弗林(Leonid Shifrin)提出了更好的解决方案:

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.

通过将HoldComplete替换为双HoldForm,可以使最后的代码更好:

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]]]

这个想法来自Wolfram Research的Robby Villegas在1999年开发者大会上的演讲.请参阅笔记本此处.

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.

这篇关于如何模拟InString []?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆