【发布时间】:2011-04-11 05:07:04
【问题描述】:
早安,
我之前认为 Mathematica 在将输入字符串(分配给InString)转换为输入表达式(分配给In)。但是一个简单的例子打破了这种解释:
In[1]:= ?f
During evaluation of In[1]:= Information::notfound: Symbol f not found. >>
In[2]:= Names["`*"]
Out[2]= {}
In[3]:= DownValues[In]//First
InString[1]
Names["`*"]
Out[3]= HoldPattern[In[1]]:>Information[f,LongForm->False]
Out[4]= \(? f\)
Out[5]= {}
您可以看到$ContextPath 中没有符号f,尽管它已在In[1] 的定义中使用。
这个例子表明,在 Mathematica 中原则上可以使用$ContextPath 中不存在的符号进行定义而不创建它们。这可能是避免使用Symbol 创建符号的方法的有趣替代方法:
In[9]:= ff := Symbol["f"]
Names["`*"]
Out[10]= {"ff"}
谁能解释在评估过程的哪个条件和哪个阶段Mathematica创建新符号?
编辑
正如 Sasha 在对这个问题的评论中注意到的那样,实际上我被默认样式表 Core.nb 中的输出单元格的默认设置 ShowStringCharacters->False 欺骗了,并且错过了 DownValues[In]//First 输出的 FullForm。在真正的符号f 没有用于In[1] 的定义中,我们也可以通过使用InputForm 看到:
In[1]:= ?f
DownValues[In]//First//InputForm
During evaluation of In[1]:= Information::notfound: Symbol f not found. >>
Out[2]//InputForm=
HoldPattern[In[1]] :> Information["f", LongForm -> False]
对不起,草率的陈述。
所以现在的问题是关于Mathematica 决定创建新Symbol 的阶段以及我们如何防止它?
例如,在上面的示例中,我们将f 输入为Symbol,但Mathematica 将其转换为String 而不创建新符号。这是MakeExpression 的内置行为:
In[1]:= ?f
InputForm[MakeExpression[ToExpression@InString[1], StandardForm]]
During evaluation of In[1]:= Information::notfound: Symbol f not found. >>
Out[2]//InputForm=
HoldComplete[Information["f", LongForm -> False]]
也许可以定义某种类型的句法结构,在评估时间之前阻止符号创建。
关于创建新符号时的评估阶段
我们可以看到,$Line 的递增发生在调用 MakeExpression 之前,但新的 Symbol 创建并为 InString 和 In 变量分配新值发生在调用 MakeExpression 之后:
In[1]:= MakeExpression[My`boxes_,My`f_]/;!TrueQ[My`$InsideMakeExpression]:=Block[{My`$InsideMakeExpression=True},Print[$Line];Print[DownValues[InString][[All,1]]];Print[DownValues[In][[All,1]]];Print[Names["`*"]];MakeExpression[My`boxes,My`f]];
In[2]:= a
During evaluation of In[2]:= 2
During evaluation of In[2]:= {HoldPattern[InString[1]]}
During evaluation of In[2]:= {HoldPattern[In[1]]}
During evaluation of In[2]:= {}
Out[2]= a
$PreRead 和 $NewSymbol 通话时间也可以这么说:
In[1]:= $NewSymbol:=Print["Names[\"`*\"]=",Names["`*"],"\nDownValues[InString]=",DownValues[InString][[All,1]],"\nDownValues[In]=",DownValues[In][[All,1]],"\nName: ",#1,"\tContext: ",#2]&
In[2]:= a
During evaluation of In[2]:= Names["`*"]={}
DownValues[InString]={HoldPattern[InString[1]]}
DownValues[In]={HoldPattern[In[1]]}
Name: a Context: Global`
Out[2]= a
$Pre 执行在对In 进行新分配并在在当前$Context 中创建所有新Symbols 之后:
In[1]:= $Pre := (Print[Names["`*"]];
Print[DownValues[In][[All, 1]]]; ##) &
In[2]:= a
During evaluation of In[2]:= {a}
During evaluation of In[2]:= {HoldPattern[In[1]],HoldPattern[In[2]]}
Out[2]= a
好像是it is not possible to intercept assigning new value for In variable。
结论:新的Symbols 是在调用$PreRead、MakeExpression 和$NewSymbol 之后但在调用$Pre 之前创建的。
【问题讨论】:
-
Doing DownValues[In] // First // FullForm 我看到 RuleDelayed[HoldPattern[In[1]],Information["f",Rule[LongForm,False]]]]
-
@Sasha 你说得对,我错过了
FullForm。这意味着实际上符号f没有像我之前想的那样在In的定义中使用。但是您能否评论一下我对符号创建的理解(在问题的第一段中描述)对吗?