The problem is not that Mathematica can not find the file, which it would indicate with another message. The problem is that Needs
insists in your package to create the context it loads and put it onto $Packages
.
To achieve that you need BeginPackage["foo`"]
and the corresponding EndPackage
in that file. Using that standard idiom will also make it possible to use the function name without the full context. That will of course also become a more minimal solution for the OPs problem.
From your comment I understand that you want to load the package but not have the package context in $ContextPath
. The answer of Simoon Rochester shows you several ways to achieve that. Here are some more:
use Needs
as usual, but remove the package name from $ContextPath
afterwards:
Needs["foo`"]; $ContextPath = DeleteCases[$ContextPath,"foo`"]
the following will do the same and is somewhat more elegant and in some senses more reliable:
Block[{$ContextPath=$ContextPath},Needs["foo`"]]
but using Block
in that way might have additional subtleties in specific situations.
Another thing you can do is to use two contexts, one for loading, the other one as the namespace of your symbols. If you put the following into file loadfoo.m:
BeginPackage["loadfoo`"];
EndPackage[];
Begin["foo`"];
hello = Function[{}, Print["Hello world!"]];
End[];
then
Needs["loadfoo`"]
will load with no error or warning messages and put "loadfoo`"
onto $ContextPath
but with no symbols in it. That file will also define foo`hello
which you can use as you seem to intend.
EDIT jkuczm has silently changed a note given above which originally read that Needs
expect the context to be added to $ContextPath
to the more correct statement that it wants the context to be added to $Packages
. Actually that is all that Needs
really checks, a fact that I was not aware of as the pair of BeginPackage
and EndPackage
do more than that and the message that Needs
just states that it wants the context to be created. Acutally you don't need to create any symbols in that context nor put it onto $ContextPath
as I always assumed. So a file "test.m" anywhere in $Path
will be loaded with no error messages by Needs
if it contains just this:
Unprotect[$Packages];
AppendTo[$Packages,"test`"];
Protect[$Packages];
Using that idea, putting the following into a file "foo.m" should also solve the OPs problem without any special care by the user who loads and without adding an empty context to $ContextPath
:
Unprotect[$Packages];
AppendTo[$Packages,"foo`"];
Protect[$Packages];
Begin["foo`"];
hello = Function[{}, Print["Hello world!"]];
End[];
which has the advantage that it can be loaded with just Needs["foo`"]
and avoids any unnecessary side effects.
Needs
callsGet
which "by default successively searches for files in the directories specified by the elements of $Path." $\endgroup$$Path
can't possibly be the answer to my question, since there is no relationship between names of files and the names of contexts defined therein. IOW, a file namedfoo.m
need not define a contextfoo`
, and, conversely, a file named something other thanfoo.m
, can define a context namedfoo`
. Since there's no correspondence whatsoever between context names and file names, I see no way in which the content of$Path
could be used to find the where a context is defined. $\endgroup$Get
just loads a file and doesn't care what is in it.Needs
should be used to load a package that follows the standard structure. It usesGet
internally, but it also does extra checks and avoids double loading. $\endgroup$