If you evaluate the following code twice, results will be different. Can anyone explain what\'s going on?
findHull[points_] := Module[{},
Needs[\"Computat
Not a direct answer to the question, but a bit too large for a comment. As another alternative, a general way to delay the symbol parsing until run-time is to use Symbol["your-symbol-name"]
. In your case, you can replace ConvexHull
on the r.h.s. of your definition by Symbol["ConvexHull"]
:
findHull[points_] :=
Module[{},
Needs["ComputationalGeometry`"];
Symbol["ConvexHull"][points]];
This solution is not very elegant though, since Symbol["ConvexHull"]
will be executed every time afresh. This can also be somewhat error-prone, if you do non-trivial manipulations with $ContextPath
. Here is a modified version, combined with a generally useful trick with self-redefinition, that I use in similar cases:
Clear[findHull];
findHull[points_] :=
Module[{},
Needs["ComputationalGeometry`"];
With[{ch = Symbol["ConvexHull"]},
findHull[pts_] := ch[pts];
findHull[points]]];
For example,
findHull[RandomReal[1, {10, 2}]]
{4, 10, 9, 1, 6, 2, 5}
What happens is that the first time the function is called, the original definition with Module
gets replaced by the inner one, and that happens already after the needed package is loaded and its context placed on the $ContextPath
. Here we exploit the fact that Mathematica replaces an old definition with a new one if it can determine that the patterns are the same - as it can in such cases.
Other instances when self-redefinition trick is useful are cases when, for example, a function call results in some expensive computation, which we want to cache, but we are not sure whether or not the function will be called at all. Then, such construct allows to cache the computed (say, symbolically) result automatically upon the first call to the function.
The problem is that even though the module is not evaluated untill you call findHull
, the symbols are resolved when you define findHull
(i.e.: The new downvalue for findHull
is stored in terms of symbols, not text).
This means that during the first round, ConvexHull
resolves to Global`ConvexHull
because the Needs
is not evaluated.
During the second round, ComputationalGeometry
is on $ContextPath
and so ConvexHull
resolves as you intended.
If you really cannot bear to load ComputationalGeometry
beforehand, just refer to ConvexHull
by its full name: ComputationalGeometry`ConvexHull
. See also this related answer.
HTH