Wolfram mathematica Mathematica什么时候创建新符号?
你好 我之前认为Mathematica在将输入字符串(分配给Wolfram mathematica Mathematica什么时候创建新符号?,wolfram-mathematica,Wolfram Mathematica,你好 我之前认为Mathematica在将输入字符串(分配给InString)转换为输入表达式(分配给中的)的阶段,在当前$Context中创建了新符号。但一个简单的例子打破了这一解释: In[1]:= ?f During evaluation of In[1]:= Information::notfound: Symbol f not found. >> In[2]:= Names["`*"] Out[2]= {} In[3]:= DownValues[In]//First InS
InString
)转换为输入表达式(分配给中的)的阶段,在当前$Context
中创建了新符号。但一个简单的例子打破了这一解释:
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
,尽管它已在[1]
中的定义中使用
此示例表明,在Mathematica中,原则上可以使用$ContextPath
中不存在的符号进行定义,而不创建它们。这可能是避免使用symbol
创建符号的有趣替代方法:
In[9]:= ff := Symbol["f"]
Names["`*"]
Out[10]= {"ff"}
有人能解释一下Mathematica在评估过程中的哪些条件和阶段创造了新的符号吗
编辑
正如Sasha在对这个问题的评论中所注意到的,实际上,默认样式表Core.nb中的输出单元格的默认设置ShowStringCharacters->False
欺骗了我,并且错过了FullForm
输出的DownValues[in]//First
。实际上,符号f
未用于[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决定在哪个阶段创建新的符号
,以及我们如何防止它?
例如,在上面的示例中,我们输入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]]
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
也许可以定义某种类型的语法结构,在计算之前阻止符号的创建
关于创建新符号时的求值阶段
我们可以看到,增量$Line
发生在调用MakeExpression
之前,而新的Symbol
创建和为InString
和中的变量赋值发生在调用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]]
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
关于和$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
在对
中的进行新分配后,以及在当前$Context
中创建所有新的符号后执行:
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
看来
结论是:在调用$PreRead
、MakeExpression
和$NewSymbol
之后创建了新的符号
,但在调用$Pre
之前,您可以使用并更好地理解符号的创建时间。但从虚拟书中,符号是在$Context
中创建的,而在$Context
和$ContextPath
中都找不到,关于编辑部分中的问题:不确定这是否是您的想法,但是在前端会话中,您可以使用$PreRead
在解析阶段将符号保留为字符串。下面是一个可能的黑客:
symbolQ = StringMatchQ[#, RegularExpression["[a-zA-Z$][a-zA-Z$`0-9]*"]] &;
ClearAll[keepSymbolsAsStrings];
SetAttributes[keepSymbolsAsStrings, HoldAllComplete];
$PreRead = # //. RowBox[{"keepSymbolsAsStrings", rest___}] :>
RowBox[{"keepSymbolsAsStrings",
Sequence @@ ({rest} //. x_String?symbolQ :>
With[{context = Quiet[Context[x]]},
StringJoin["\"", x, "\""] /;
Head[context] === Context])}] &;
仅当符号尚不存在时,才会将其转换为字符串(通过上下文[symbol\u string\u name]
进行检查)。比如说
In[4]:= keepSymbolsAsStrings[a+b*Sin[c]]//FullForm
Out[4]//FullForm= keepSymbolsAsStrings[Plus["a",Times["b",Sin["c"]]]]
首先定义keepSymbolsAsStrings
非常重要,以便创建此符号。这使得它重新进入:
In[6]:= keepSymbolsAsStrings[a+b*Sin[c]*keepSymbolsAsStrings[d+e*Sin[f]]]//FullForm
Out[6]//FullForm=
keepSymbolsAsStrings[Plus["a",Times["b",Sin["c"],
keepSymbolsAsStrings[Plus["d",Times["e",Sin["f"]]]]]]]
现在,您可以在代码解析后以自己喜欢的方式处理这些符号(保留为字符串)。您也可以使用不同的symbolQ
函数-为了举例,我只使用了一个简单的函数
但这对软件包不起作用。我不认为有一种简单的方法可以对包执行此操作。一种简单的方法是动态地重新定义需求
,以类似于预处理阶段的方式在字符串级别修改源代码,并对修改后的源代码有效地调用需求
。但是字符串级别的源代码修改通常是脆弱的
嗯
编辑
上述代码有一个缺陷,即很难区分哪些字符串是字符串,哪些是由上述函数转换的符号。通过将clearl[keepSymbolsAsStrings]
更改为clearl[keepSymbolsAsStrings,symbol]
和StringJoin[“\”,x,“\”]
byRowBox[{“symbol”,“[”,StringJoin[“\”,x,“\”,“]),可以修改上述代码
跟踪结果表达式中的哪些字符串对应于转换后的符号
编辑2
以下是修改后的代码,它基于MakeExpression
而不是@Alexey建议的$PreRead
:
symbolQ = StringMatchQ[#, RegularExpression["[a-zA-Z$][a-zA-Z$0-9`]*"]] &;
ClearAll[keepSymbolsAsStrings, symbol];
SetAttributes[keepSymbolsAsStrings, HoldAllComplete];
Module[{tried},
MakeExpression[RowBox[{"keepSymbolsAsStrings", rest___}], form_] :=
Block[{tried = True},
MakeExpression[
RowBox[{"keepSymbolsAsStrings",
Sequence @@ ({rest} //. x_String?symbolQ :>
With[{context = Quiet[Context[x]]},
RowBox[{"symbol", "[", StringJoin["\"", x, "\""], "]"}] /;
Head[context] === Context])}], form]
] /;!TrueQ[tried]
]
我们需要Todd Gayley的例子来打破MakeExpression
定义中的无限递归。以下是例子:
In[7]:= keepSymbolsAsStrings[a+b*Sin[c]]//FullForm
Out[7]//FullForm= keepSymbolsAsStrings[Plus[symbol["a"],Times[symbol["b"],Sin[symbol["c"]]]]]
In[8]:= keepSymbolsAsStrings[a+b*Sin[c]*keepSymbolsAsStrings[d+e*Sin[f]]]//FullForm
Out[8]//FullForm= keepSymbolsAsStrings[Plus[symbol["a"],Times[symbol["b"],Sin[symbol["c"]],
keepSymbolsAsStrings[Plus[symbol["d"],Times[symbol["e"],Sin[symbol["f"]]]]]]]]
此方法更简洁,因为最终用户仍然可以使用$PreRead
。我认为您对输入解析为表达式时创建符号的基本理解是正确的
微妙之处在于,行开头的?
(以及
)专门进行解析,以允许字符串不需要引号。(这里的隐式字符串是模式,如*Min*
用于?
以及
的文件名)执行DownValues[In]//首先//FullForm我看到RuleDelayed[HoldPattern[In[1]],信息[“f”,规则[LongForm,False]]].@Sasha你是对的,我错过了FullForm
。这意味着在真正意义上,符号f
并不像我之前所想的那样在的定义中使用。但是你能评论一下我对符号创造的理解(在问题的第一段描述)对吗?谢谢你这个聪明的解决方案!但可能是新定义的方法