From: Chris Degnen on
I have some code which reads in rules using variable names that
already exist, e.g. a and b. I used Block to achieve the replacement
instructions, but was surprised to have to use BeginPackage and Begin
again to get the context right. Can anybody comment on what's going
on here?


BeginPackage["Test`"];
TestFunction::usage = "Testing contexts";
Begin["`Private`"];
TestFunction[] := Module[{},

a = 1;
b = 1;

BeginPackage["Test`"];
Begin["`Private`"];

Block[{a, b},
x = Get["x.dat"];
a2 = a /. x;
b2 = b /. x;];

End[];
EndPackage[];

Return[{a2, b2}]];

End[];
EndPackage[];

x = {a -> "one", b -> "two"};
x >> x.dat;
TestFunction[]

From: Albert Retey on
Am 31.03.2010 12:27, schrieb Chris Degnen:
> I have some code which reads in rules using variable names that
> already exist, e.g. a and b. I used Block to achieve the replacement
> instructions, but was surprised to have to use BeginPackage and Begin
> again to get the context right. Can anybody comment on what's going
> on here?

I think everything behaves as expected. The function definition of
TestFunction is made in context "Test`Private`" so the symbols a and b
used there are actually Test`Private`a and Test`Private`b. When you use
the function, it runs in context Global` , so when you read the file
with Get the new symbols are created as Global`a and Global`b so that
the patterns in TestFunction don't match. Only if you do set the Context
to Test`Private` before reading the file, the symbols a and b will be in
the context Test`Private` and the patterns will match.

> BeginPackage["Test`"];
> TestFunction::usage = "Testing contexts";
> Begin["`Private`"];
> TestFunction[] := Module[{},
>
> a = 1;
> b = 1;
>
> BeginPackage["Test`"];
> Begin["`Private`"];
>
> Block[{a, b},
> x = Get["x.dat"];
> a2 = a /. x;
> b2 = b /. x;];
>
> End[];
> EndPackage[];
>
> Return[{a2, b2}]];
>
> End[];
> EndPackage[];
>
> x = {a -> "one", b -> "two"};
> x >> x.dat;
> TestFunction[]
>

here are some suggestions for your code: a Module with an empty variable
list does nothing, so there is no reason to use it. Also the Return at
the end is not necessary. Finally I don't see any good reason to use
symbols in your replacement rules. If you use strings instead you will
avoid any context issues. In some cases this might also be more
efficient, after all a symbol is something much more complicated than
just a string. The following is basically doing the same thing with much
less effort:

BeginPackage["Test`"];
TestFunction::usage = "Testing contexts";
Begin["`Private`"];
TestFunction[] := ({"a", "b"} /. Get["x.dat"]);
End[];
EndPackage[];

x = {"a" -> "one", "b" -> "two"};
x >> x.dat;
TestFunction[]




From: Chris Degnen on
On 31 Mar, 12:51, Albert Retey <a...(a)gmx-topmail.de> wrote:

> ... I don't see any good reason to use symbols in your
> replacement rules. If you use strings instead you will avoid
> any context issues. In some cases this might also be
> more efficient, after all a symbol is something much more
> complicated than just a string. The following is basically
> doing the same thing with much less effort:
>
> BeginPackage["Test`"];
> TestFunction::usage = "Testing contexts";
> Begin["`Private`"];
> TestFunction[] := ({"a", "b"} /. Get["x.dat"]);
> End[];
> EndPackage[];
>
> x = {"a" -> "one", "b" -> "two"};
> x >> x.dat;
> TestFunction[]


Thanks Albert. Actually, I had to add in a reset (as shown) for the
ContextPath since its rearrangement by EndPackage[] was causing some
odd problems in my application. It works fine with the reset, but I
will probably switch to using strings as you suggested.

BeginPackage["Test`"];
TestFunction::usage = "Testing contexts";
Begin["`Private`"];
TestFunction[] := Module[{contextpath},

a = 1;
b = 1;

contextpath = $ContextPath;
BeginPackage["Test`"];
Begin["`Private`"];
Block[{a, b},

x = Get["x.dat"];
a2 = a /. x;
b2 = b /. x;

];

End[];
EndPackage[];
$ContextPath = contextpath;

{a2, b2}];

End[];
EndPackage[];

x = {a -> "one", b -> "two"};
x >> x.dat;
TestFunction[]