You've got more than one question here, but I'm not sure which problem you're really trying to solve.
- From the title: "How does
Needs["foo`"]
find the file that defines contextfoo`
?"
Needs
looks for a file in the $Path
or in the current working directory named foo.m
or foo.wl
. (As a complication, there is also a list of Paclet directories that it looks ina list of Paclet directories that it looks in, but you can ignore that if you're not using PacletInfo.m
files. The paclet files can be used to register packages where the file names don't correspond to the contexts, however, which may address one of your other questions.)
- What else must I put in ./client.m, besides
Needs["foo`"]
, so that the expressionfoo`hello[]
evaluates properly?
You don't need to put anything else. foo`hello[]
should already be evaluating properly with what you have (assuming foo.m
has been found on the $Path
). The warning message that you get when you evaluate Needs
doesn't affect that.
Likewise for the question from your comment about making the the use of full context manditory -- you have already done that, by using Begin
instead of BeginPackage
, so that the context foo`
is not added to the $Contexts
variable.
If it is the warning message that is primarily concerning you, the best approach is to use Get["foo`"]
rather than Needs
, since Needs
is set up to expect the context to be registered, while Get
doesn't care.
If you want to use Needs
because you only want to load foo.m
once in the session, you could instead use the Once
function (new in version 11): Once[Get["foo`"]]
. Or you could just use Quiet[Needs["foo`"]]
or Off[Needs::nocont]
to suppress the warning message.