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是“内部”函数,因此它们保留在MyPackage
Private
Context中答案顶部带有
Block
的方法简单而优雅,但是如果具有相同短(字符串)的符号,则会(无声地)失败名称确实存在于当前$ContextPath上的某些上下文中(这不一定意味着阴影)。这方面的一个简单例子是:
f[x]:=x^2;块[{$Context=“Test'Private'”},ToExpression[“f”][x]
。这就是我在回答中使用
BeginPackage-EndPackage
的原因之一,他们会解决这个问题。或者,您可以使用
块[{$Context=“Test'Private'”,$ContextPath={“Test'”,“System'}},…]