关于您在edit部分:不确定这是否是您的想法,但在前端会话中您可以使用$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
Edit
上面的代码有一个缺陷,即很难区分哪些字符串是字符串,哪些是上述函数转换的符号。您可以通过更改上面的代码来修改ClearAll[keepSymbolsAsStrings]
to ClearAll[keepSymbolsAsStrings, symbol]
and StringJoin["\"", x, "\""]
by RowBox[{"symbol", "[", StringJoin["\"", x, "\""], "]"}]
跟踪结果表达式中的哪些字符串对应于转换后的符号。
Edit 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 https://stackoverflow.com/questions/4198961/what-is-in-your-mathematica-tool-bag/5149656#5149656托德·盖利 (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
仍然可供最终用户使用。