2
$\begingroup$

The more I study, the less I understand.

This is the HelloWorld package:

BeginPackage["HelloWorld`"];
helloWorld::usage="helloWorld !";
Begin["`Private`"];
helloWorld[arg_]:=arg+1;
End[];
EndPackage[];

This code works as obviously intended

(* code 1 *)
With[
{packageFile=FileNameJoin[{NotebookDirectory[],"HelloWorld.m"}]},
Needs["HelloWorld`",packageFile];
];
Print @ helloWorld[1];
Quit[];

On the contrary, this one

(* code 2 *)
With[
{packageFile=FileNameJoin[{NotebookDirectory[],"HelloWorld.m"}]},
Needs["HelloWorld`",packageFile];
Print @ helloWorld[1];
];
Quit[];

generates a message:

helloWorld::shdw: "Symbol ("helloWorld") appears in multiple contexts ({"HelloWorld`", "Global`"}); "

Now, my (bad !) reasoning is: In (* code 1 *), Needs performs its role, at a later time the helloWorld symbol is "publicly visible" (from inside the Global context), and when the function is called there are no motives to create, wherever, a new one named "helloWorld". In (* code 2 *), the same should happens; all in all the $Context inside and outside While[] is the same, as seen by

$Context
With[{a = 1}, Print @ $Context]

Quoting Mathematica's Help:

Conflicts can occur not only between symbols in different packages, but also between symbols in packages and symbols that you introduce directly in your Mathematica session.If you define a symbol in your current context, then this symbol may become shadowed by another symbol with the same short name in packages that you read in.

The point is: in (* code 2 *) I haven't defined a new helloWorld symbol, only invoked an existing and visible one.

In How to load a package without naming conflicts? is explained:

... in this way, you don't have to do anything afterwards, since, once the scope of Block is left, the `$ContextPath automatically is reset to its previous value.

But I can't understand how this consideration 'overwrites' the above mentioned one about $Context.

$\endgroup$
  • 2
    $\begingroup$ This is a problem with the parsing in FrontEnd, not scoping. For the lines on the top-level, FE parses and executes them one by one, sending them as separate evaluations to the kernel. If you enclose code in some wrapper (With, in your case), all the code inside is parsed as a whole, and so in your second case you create a global symbol at the parsing stage, even before your package gets loaded - and so you get the shadowing. See this discussion for a similar issue. $\endgroup$ – Leonid Shifrin Apr 17 '16 at 14:34
  • $\begingroup$ Thanks for the reply !! Do you mean that respect to a standalone kernel (* code 1*) and (* code 2 *) work the same ? $\endgroup$ – mitochondrial Apr 17 '16 at 14:53
  • 2
    $\begingroup$ Not sure what you mean. You can either run the code from the FrontEnd, or inside the package, or from a text interface. In each case, the result depends on how the code is parsed and executed. I don't remember off hand the package and text-interface case, but chances are you'd get the same behavior there as well, given that With and everything inside it is a single expression, and so should be parsed entirely before execution. It may however be not the case if e.g. the package parser works differently. I don't have the time to test now, but it isn't hard. $\endgroup$ – Leonid Shifrin Apr 17 '16 at 15:07
  • $\begingroup$ I have just checked that in batch mode (* code 1*) and (* code 2*) both give 2 $\endgroup$ – mitochondrial Apr 17 '16 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.