gpt4 book ai didi

wolfram-mathematica - Mathematica 何时创建新符号?

转载 作者:行者123 更新时间:2023-12-04 04:09:58 32 4
gpt4 key购买 nike

再会,

我之前认为 Mathematica 在当前 $Context 中创建了新符号在将输入字符串(分配给 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]= {}

可以看到没有符号 f$ContextPath尽管它已经在 In[1] 的定义中使用了.

这个例子表明,在 Mathematica 中原则上可以用 $ContextPath 中不存在的符号进行定义。无需创建它们。这可能是使用 Symbol 避免符号创建方法的有趣替代方法。 :
In[9]:= ff := Symbol["f"]
Names["`*"]
Out[10]= {"ff"}

有人能解释一下 Mathematica 在评估过程的哪个条件和哪个阶段创建新符号吗?

编辑

正如 Sasha 在对这个问题的评论中注意到的那样,实际上我被默认欺骗了 ShowStringCharacters->False默认样式表 Core.nb 中输出单元格的设置并错过了 FullForm DownValues[In]//First 的输出.中真符号 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 的阶段。我们如何预防?
例如,在上面的例子中我们输入 fSymbol但 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但新 SymbolInString 创建和分配新值和 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 进行新赋值后执行制作并在创建所有新之后 Symbol s 在当前 $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

看来 it is not possible to intercept assigning new value for In variable .

结论:新 Symbol s 是在调用 $PreRead 后创建的, MakeExpression$NewSymbol但在打电话之前 $Pre .

最佳答案

关于编辑部分中的问题:不确定这是否是您的想法,但在前端 session 中,您可以使用 $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])}] &;

仅当符号尚不存在时(通过 Context[symbol_string_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功能 - 为了举例,我只使用一个头脑简单的功能。

但这不适用于包。我没有看到对包执行此操作的直接方法。一种简单的方法是动态重新定义 Needs ,以类似于预处理阶段的方式在字符串级别修改源,并有效调用 Needs在修改后的源上。但是字符串级别的源代码修改通常很脆弱。

HTH

编辑

上面的代码有一个缺陷,即很难区分哪些字符串是字符串,哪些是由上述函数转换的符号。您可以通过更改 ClearAll[keepSymbolsAsStrings] 来修改上面的代码至 ClearAll[keepSymbolsAsStrings, symbol]StringJoin["\"", x, "\""]来自 RowBox[{"symbol", "[", StringJoin["\"", x, "\""], "]"}]跟踪结果表达式中的哪些字符串对应于转换后的符号。

编辑 2

这是修改后的代码,基于 MakeExpression而不是 $PreRead ,正如@Alexey 所建议的:
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]
]

我们需要 trick 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最终用户仍然可以使用。

关于wolfram-mathematica - Mathematica 何时创建新符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5616966/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com