Wolfram mathematica 从包中获取当前上下文
我的笔记本里有如下内容Wolfram mathematica 从包中获取当前上下文,wolfram-mathematica,Wolfram Mathematica,我的笔记本里有如下内容 test1[g_] := (g == 5); test2[g_] := (g == 6); tests={"test1", "test2"} ToExpression[#][5] & /@ tests 当我将此代码放入包中时,它不起作用,因为test1现在被称为MyPackage'Private'test1。如何修改最后一行以使此代码在包内和笔记本内运行 更新 这就是为什么我要做的是表达,而不是使用符号。回想起来,使用符号可能更容易 我有一个我调用的函数,比如g
test1[g_] := (g == 5);
test2[g_] := (g == 6);
tests={"test1", "test2"}
ToExpression[#][5] & /@ tests
当我将此代码放入包中时,它不起作用,因为test1
现在被称为MyPackage'Private'test1
。如何修改最后一行以使此代码在包内和笔记本内运行
更新
这就是为什么我要做的是表达,而不是使用符号。回想起来,使用符号可能更容易
我有一个我调用的函数,比如getGraphs[“无叶”、“平面”、“树”…]
来获取所有无叶、平面而非树的图。其中一些字符串是GraphData
中的类,而其他字符串是我自己的类。对于我自己的每个类,我都有一个同名的函数,比如测试属性的LeafFree
。在笔记本中,使用上面的来表达代码是实现这一点的最快方法
getGraphs[n_Integer, cl__] := getGraphs[{n, n}, cl];
getGraphs[{nmin_Integer, nmax_Integer}, cl__] :=
Module[{maxgraphnum = 100},
customClasses = {"isLeafFree", ! "isLeafFree"};
classes = {cl}\[Backslash]customClasses;
builtinClasses =
GraphData["Classes"] \[Tilde] (Not /@ GraphData["Classes"]);
Assert[classes \[Subset] builtinClasses];
isLeafFree[gname_] :=
FreeQ[GraphData[gname, "DegreeSequence"], 0 | 1];
posClasses = Cases[classes\[Backslash]customClasses, _String];
posGroup =
If[posClasses == {}, GraphData[nmin ;; nmax],
GraphData[posClasses, nmin ;; nmax]];
negClasses = classes\[Backslash]posClasses;
negGroups = GraphData[#[[1]], nmin ;; nmax] & /@ negClasses;
result = Complement[posGroup, Sequence @@ negGroups];
customTest[g_] :=
And @@ (ToExpression[#][g] & /@ ({cl} \[Intersection]
customClasses));
(*result=Take[result,Min[Length[result],100]];*)
result = Select[result, customTest]
]
我同意上面的评论,你也许应该有一个令人信服的理由去做这件事,但这里是。下面是我在这种情况下使用的代码,它允许在运行时在您喜欢的任何上下文中解析您的符号:
SetAttributes[ParseTimeNameSpaceWrapper,HoldFirst];
Options[ParseTimeNameSpaceWrapper] = {
LocalizingContext->"MyLocalizingContext`",
DefaultImportedContexts:>{"Imported1`", "Imported2`"},
ExtraImportedContexts:> {}
};
ParseTimeNameSpaceWrapper[code_,opts:OptionsPattern[]]:=
Module[{result,
context = OptionValue[LocalizingContext],
defcontexts = OptionValue[DefaultImportedContexts],
extraContexts = OptionValue[ExtraImportedContexts],
allContexts},
allContexts = {Sequence@@defcontexts,Sequence@@extraContexts};
BeginPackage[context,If[allContexts==={},Sequence@@{},allContexts]];
result = code;
EndPackage[];
result
];
您可以使用选项指定这些符号存在的某些上下文,这些上下文要在解析阶段导入。您可以从任何软件包或笔记本中调用它,符号将根据您指定的上下文进行解析
嗯
编辑:
响应注释(因为它使问题更加具体):毫无疑问,在运行时Context[]
将显示调用函数的当前上下文(在这种情况下为全局上下文)。我的意思是:Context
有一个语法Context[symbol]
,如果任何符号在$ContextPath
上,就给出它的上下文。例如,Context[getGraphs]
返回Bulatov'showGraphs'
。因此,如果需要自动确定某些导出函数的上下文,可以调用context[function]
。您可以使用它来构造该包的其他(私有)函数的全名。下面是一个独立的示例:
In[1]:=
BeginPackage["MyTest`"];
f[x_, y_, context_: Context[f]] :=
Module[{f1str = "function1", f2str = "function2", f1, f2},
{f1, f2} = ToExpression[context <> "Private`" <> #] & /@ {f1str, f2str};
f1[x, y];
f2[x, y];];
Begin["`Private`"];
function1[x_, y_] := Print["In function1: arguments are ", x, " , ", y];
function2[x_, y_] := Print["In function2: arguments are ", x, " , ", y];
End[]
EndPackage[];
Out[6]= "MyTest`Private`"
In[8]:= f[1, 2]
During evaluation of In[8]:= In function1: arguments are 1 , 2
During evaluation of In[8]:= In function2: arguments are 1 , 2
[1]中的:=
BeginPackage[“我的测试”];
f[x,y,上下文:上下文[f]]:=
模块[{f1str=“function1”,f2str=“function2”,f1,f2},
{f1,f2}=ToExpression[context“Private`”#]&/{f1str,f2str};
f1[x,y];
f2[x,y];];
开始[“`Private`]”;
function1[x,y]:=Print[“在function1中:参数是,”,x,“,”,y];
function2[x,y]:=Print[“在function2中:参数是,”,x,“,”,y];
结束[]
EndPackage[];
Out[6]=“MyTest`Private`”
在[8]:=f[1,2]
在[8]:=函数1中的求值过程中:参数为1,2
在[8]:=函数2中的求值过程中:参数为1,2
其中x,y
只是一些示例参数。然后,您永远不会实际提供最后一个参数,但您可以在函数中使用context
变量,为其他函数构造长名称,如上面的示例代码所示。或者您可以在函数体中直接使用上下文[f],而不向其添加任何参数。ToExpression
在创建符号时使用当前绑定的$Context
,因此您可以强制在特定上下文中解释表达式,从而:
Block[{$Context="MyPackage`Private`"}, ToExpression[#][5]] & /@ tests
我不确定我是否理解原始问题的情况。您可以使用$context
或context[]
获取当前上下文。。。但是ToExpression
将自动使用当前上下文而无需干预
如果我在笔记本上运行展示的代码,它就可以正常工作。如果我这样运行它:
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
tests = {"test1", "test2"}
ToExpression[#][5] & /@ tests
End[]
(* in the package file *)
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
End[]
(* in the notebook *)
tests = {"test1", "test2"}
ToExpression[#][5] & /@ tests
(* in the package *)
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
tests = {"test1", "test2"};
With[{context = $Context},
runTests[] := Block[{$Context = context}, ToExpression[#][5]] & /@ tests
]
End[]
(* in the notebook *)
MyPackage`Private`runTests[]
。。。它也很好用。我可以让它失败,如果我这样运行它:
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
tests = {"test1", "test2"}
ToExpression[#][5] & /@ tests
End[]
(* in the package file *)
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
End[]
(* in the notebook *)
tests = {"test1", "test2"}
ToExpression[#][5] & /@ tests
(* in the package *)
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
tests = {"test1", "test2"};
With[{context = $Context},
runTests[] := Block[{$Context = context}, ToExpression[#][5]] & /@ tests
]
End[]
(* in the notebook *)
MyPackage`Private`runTests[]
。。。这不仅失败了,而且在笔记本的上下文中产生了虚假的符号。您可以使用上面的块
配方解决此问题
如果要捕获在加载包代码时生效的上下文,可以执行以下操作:
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
tests = {"test1", "test2"}
ToExpression[#][5] & /@ tests
End[]
(* in the package file *)
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
End[]
(* in the notebook *)
tests = {"test1", "test2"}
ToExpression[#][5] & /@ tests
(* in the package *)
Begin["MyPackage`Private`"]
test1[g_] := (g == 5);
test2[g_] := (g == 6);
tests = {"test1", "test2"};
With[{context = $Context},
runTests[] := Block[{$Context = context}, ToExpression[#][5]] & /@ tests
]
End[]
(* in the notebook *)
MyPackage`Private`runTests[]
runTests
使用With
将私有包上下文注入其定义中
正如JANUS指出的那样,使用符号比字符串更好,因为它们自动地管理整个上下文问题——但是这假设你的实际用例允许使用符号。
你有没有尝试过代码> String Eng[[上下文][O],[/{“Test1”,“Test2”} /代码>我会认为<代码>表达式< /代码>是坏的风格鸭子。使用字符串而不是符号有什么原因吗??我会考虑<代码> TestsasByths= {Test1,Test2} /代码>和<代码> [ TestsasSt符号(5)] /代码>更好-并且它在两种情况下都会起作用吗?今天每个人都很害羞:)贝里萨里乌斯:是的,不起作用,见下面我的评论。Janus:我使用ToExpression是因为我在做一些类似于MyPackage'doChecks[{“test1”,“test2”}]
的事情,其中test1
是在函数doChecks
中定义的函数名Context[]
不起作用的原因是因为所包含的函数被放入了Needs
上的全局`上下文中,因此,Context[]
在执行时是全局的,而test1、test2是“内部”函数,因此它们保留在MyPackagePrivate
Context中答案顶部带有Block
的方法简单而优雅,但是如果具有相同短(字符串)的符号,则会(无声地)失败名称确实存在于当前$ContextPath上的某些上下文中(这不一定意味着阴影)。这方面的一个简单例子是:f[x]:=x^2;块[{$Context=“Test'Private'”},ToExpression[“f”][x]
。这就是我在回答中使用BeginPackage-EndPackage
的原因之一,他们会解决这个问题。或者,您可以使用块[{$Context=“Test'Private'”,$ContextPath={“Test'”,“System'}},…]