I'm just going to go ahead an rephrase the answer. The problem as Leonid points out is akin to shadowing. Here is a very simple example of the behavoir:
Remove[test`x, x]
(
Begin["test`"];
x = 42;
End[];
{x, test`x}
)
{42,test`x}
Remove[test`x, x]
Begin["test`"];
x = 42;
End[];
{x, test`x}
{x,42}
If you use Trace You will see that in the second example everything is evaluated line-by-line, which means that when we get to x=42 the active context is test`, however in the first case, we initially evaluate the CompoundExpression which means we put Global`x into scope, which means we already have an x defined when we evaluate x=42 thus it's interpreted as Global`x=42.
A way to get around this is to use the fact that MakeBoxes will automatically remove any context currently in $ContextPath while ToExpression Automatically puts any symbol not found in any context into $Context. Here I exclude the System` context in order to avoid scoping for example Sin to test`Sin:
SetAttributes[ContextScope, HoldAll]
ContextScope[context_, expression_, exclude_: {"System`"}] :=
Block[{held},
Block[{$ContextPath = Complement[$ContextPath, {"System`"}]}, held = MakeBoxes[expression]];
Block[{$Context = context, $ContextPath = {context}},
ToExpression[held]]
]
ContextScope["test`", x = Sin[0]]
{x, test`x}
{x,0}
This will however still put Global`x in scope, it simply does not assing a value to it. So any new call to x=somethign will assign a value to Global`x and not to test`x as would normally be expected if you had done a line by line evaluation of the context switching.
Module(without localizing variables) is misleading here, and can be as well removed. – Leonid Shifrin Sep 10 '12 at 10:49