# How to define a package without adding it to $ContextPath How can you introduce a package, so that it is listed in $Packages, without adding it to $ContextPath? Note that this question is concerned with defining a package when evaluating code, e.g. through evaluating a cell, rather than loading a package from a file. This is useful if you want to add capabilities without introducing new "bare" symbols in any way -- they live in their own context and must be referenced through an explicit context, unless the user adds that context back to the context path. - Do I understand correctly that you cannot use the equivalent of Block[{$ContextPath}, Needs["Combinatorica"]] because the package is defined in a notebook, and it must be in multiple, separate input lines (therefore can't be wrapped)? BeginPackage affects parsing, so it takes effect only starting with the next input. –  Szabolcs Feb 4 '13 at 23:06
This seems to work even if you were to define the package and not load it (basically what Szabolcs said) –  The Toad Feb 4 '13 at 23:19
@rm-rf Nope, that can't be used if you define the package in a cell. The reason is that as soon as you wrap the definition in Block, it becomes a single input that is parsed before BeginPackage is evaluated and changes the context. So while it may appear to work on first try, the package symbols will all be created in the Global context. –  Szabolcs Feb 4 '13 at 23:21
@Szabolcs Ah yes, you're right. –  The Toad Feb 4 '13 at 23:22
Ref: stackoverflow.com/questions/7917550/… BTW I upvoted this because when one starts to think of alternative solutions, it'll become clear that Joel's solution is not as trivial to figure out as it looks. –  Szabolcs Feb 4 '13 at 23:22

Just using DeleteCases seems to work too:

  BeginPackage["ChurchNumerals"];
ZERO::usage = "ZERO is the Church encoding of zero";
ONE::usage = "ONE is the Church numeral encoding of the integer 1";
TWO::usage = "TWO is the Church numeral encoding of the integer 2";
Begin["Private"];
ZERO = Function[f, Function[n, n]];
ONE = Function[f, Function[n, f[n]]];
TWO = Function[f, Function[n, f[f[n]]]];
End[];
EndPackage[];
$ContextPath = DeleteCases[$ContextPath, "ChurchNumerals"]

-
While I appreciate the other answers, this is direct and simple and seems most like "the answer". –  Joel Klein Feb 5 '13 at 18:34

There is a simpler way:

BeginPackage["ChurchNumerals"];

ZERO::usage = "ZERO is the Church encoding of zero";
ONE::usage = "ONE is the Church numeral encoding of the integer 1";
TWO::usage = "TWO is the Church numeral encoding of the integer 2";

Begin["Private"];

ZERO = Function[f, Function[n, n]];
ONE = Function[f, Function[n, f[n]]];
TWO = Function[f, Function[n, f[f[n]]]];

End[];

Block[{$ContextPath}, EndPackage[]];  It is the EndPackage which is responsible for keeping the context on the $ContextPath, so you can just Block only it.

Note that putting a Block around the whole thing won't work in the FrontEnd, since only the top-level statements are parsed one by one in a cell - so in that case, the symbols would end up created in a wrong (Global) context.

-
I think there should not be different parsers. It is hard to figure out the difference, harder to program around them and even harder to try to teach this. –  Rolf Mertig Feb 5 '13 at 0:41
Why does this work? I find it weird that a line like this Block[{$ContextPath}, EndPackage[]]; can change the $ContextPath. Big +1 of course, I'm learning something new –  Rojo Feb 5 '13 at 0:49
@Rojo This Block does not change the $ContextPath, it prevents the EndPackage from changing it globally. It is EndPackage which attempts to change things here. Soon, I will run out of tricks to surprise you :-). – Leonid Shifrin Feb 5 '13 at 0:53 ...but before running that line the $ContextPath is just {ChurchNumerals,System}, and afterwards it goes back to having Global and the rest –  Rojo Feb 5 '13 at 0:56
I wouldn't have guessed, confusing. Even if it were true that you run out of tricks, we've come a long way –  Rojo Feb 5 '13 at 1:45

One way to do this is by taking note of how EndPackage works -- by adding \$Context to \$ContextPath:

ChurchNumeralsPrivateprevContext = Context[];
BeginPackage["ChurchNumerals"];
ZERO::usage = "ZERO is the Church numeral encoding of zero";
ONE::usage = "ONE is the Church numeral encoding of the integer 1";
TWO::usage = "TWO is the Church numeral encoding of the integer 2";
Begin["Private"];
ZERO = Function[f, Function[n, n]];
ONE = Function[f, Function[n, f[n]]];
TWO = Function[f, Function[n, f[f[n]]]];
End[];
$Context = ChurchNumeralsPrivateprevContext; EndPackage[];  Now the package is on $Packages but not \$ContextPath, and is used qualified with the package name:

Map[#[Function[n, n + 1]][0] &,
{ChurchNumeralsZERO, ChurchNumeralsONE, ChurchNumeralsTWO}]

-
I would use the variable to store the context path and restore it after EndPackage instead of the current context. Simpler for the cases where EndPackage also adds the dependency list (second argument of BeginPackage) –  Rojo Feb 4 '13 at 23:48
Yeah, that works too. In my case I'm bending over backward not to introduce anything into context path, so I didn't think of that case of the 2nd argument to BeginPackage. –  Joel Klein Feb 5 '13 at 4:04