Re: Second argument of BeginPackage, revisited
- To: mathgroup at smc.vnet.net
- Subject: [mg78537] Re: Second argument of BeginPackage, revisited
- From: Andrew Moylan <andrew.j.moylan at gmail.com>
- Date: Tue, 3 Jul 2007 06:51:59 -0400 (EDT)
- References: <f5td66$36j$1@smc.vnet.net><f62k72$bod$1@smc.vnet.net>
Right, there is no irregularity in the value of $ContextPath after executing EndPackage[]. As stated in the documentation, after the EndPackage[] statement corresponding to BeginPackage["a`"], only "a`" has been added to the original value of $ContextPath. The irregularity that I am referring to is in the different values of $ContextPath *between* the calls to BeginPackage[] and EndPackage[]. Compare the output of these two examples: BeginPackage["a`", {"PhysicalConstants`"}] $ContextPath Output: {"a`", "PhysicalConstants`", "System`"} BeginPackage["a`"] Needs["PhysicalConstants`"] $ContextPath Output: {"PhysicalConstants`", "Units`", "a`", "System`"} As Don DuBois has pointed out in a private message, the correct way to obtain the behaviour of Needs[] when declaring packages is not to use the second argument of BeginPackage, but instead to use Needs[] *twice*, like this: BeginPackage["a`"] Needs["b`"] (* code block 2 *) EndPackage[] Needs["b`"] On Jul 2, 9:08 pm, dh <d... at metrohm.ch> wrote: > Hi Andrew, > > you are correct, BeginPackage["a`",{"b`",..}].. EndPackage[] will put > > all the additional contexts "b`".. into $ContextPath. Therefore, all > > variables exported by these contexts will be available. > > On the other hand, BeginPackage["a`"] Needs["b`"];.. Endpackage[] will > > only put "a`" into $ContextPath, therefore, variables from "b`".. are > > not available afterwards. > > Daniel > > Andrew Moylan wrote: > > On Jun 28, 6:37 pm, dh <d... at metrohm.ch> wrote: > >> Hi Andrew, > > >> you misunderstood the Package concept. BeginPackage["a`", {"b`"}] will > > >> place b in the $ContextPath so that its content can be found, but it > > >> does not put b in Context[], so that new variables are not created in b. > > >> The following may help. Start a new session and enter: > > >> BeginPackage["b`",{"PhysicalConstants`"}] > > >> Print[SpeedOfLight]; > > >> Print[Context[]]; > > >> Print[$ContextPath]; > > >> EndPackage[] > > >> hope this helps, Daniel > > >> Andrew Moylan wrote: > >>> Unfortunately (in my opinion), BeginPackage["a`", {"b`"}] does not *quite* > >>> call Needs[] on its second argument(s). > >>> Suppose b.m looks like this: > >>> BeginPackage["b`", {"PhysicalConstants`"}] > >>> (* some code *) > >>> EndPackage[] > >>> Then calling Needs["b`"] in a new kernel results in "PhysicalConstants`" > >>> being on the list of contexts, so that e.g. SpeedOfLight works as expected. > >>> But calling BeginPackage["a`", {"b`"}] instead does *not* put > >>> PhysicalConstants on the list of contexts during the definition of the > >>> package, so that e.g. SpeedOfLight results in the creation of a new, useless > >>> symbol called a`SpeedOfLight. > >>> Finally, for maximum confusion (in my opinion), once EndPackage[] is called > >>> to finish loading the "a`" package, "PhysicalConstants`" *is* placed on the > >>> list of contexts, causing shadowing between a`SpeedOfLight and > >>> PhysicalConstants`SpeedOfLight. > >>> Effectively, BeginPackage appears to > >>> 1. Call Needs[] on its second arguments, then > >>> 2. Temporarily remove from the context path any extra contexts those > >>> packages added to the context path, then finally > >>> 3. Put all those temporarily removed packages back onto the context path > >>> once EndPackage[] is called. > >>> Can anyone help me understand why this behaviour is useful? > > > Daniel, you have misunderstood the question in my post. > > > Here is the crucial irregularity to which I refer: > > > BeginPackage["a`", {"b`"}] > > (* code block 1 *) > > EndPackage[] > > > BeginPackage["a`"] > > Needs["b`"] > > (* code block 2 *) > > EndPackage[] > > Needs["b`"] > > > The above two alternatives are not identical, because (strangely, in > > my opinion) code in code block 1 cannot refer to symbols defined in > > any packages declared in the second argument of the BeginPackage > > statement for b` (in b.m); whereas code in code block 2 *can* refer to > > such symbols. > > > Here is a different way to understand the irregularity: > > > Suppose this code works correctly: > > > Needs["b`"] > > (* code block 3 *) > > > Then, will this code generally also work correctly? > > > BeginPackage["whatever`", {"b`"}] > > (* code block 3 *) > > > The answer is no, because of the way BeginPackage apparently modifies > > the value of $ContextPath after calling Needs[] on its second argument.
- Follow-Ups:
- Re: Re: Second argument of BeginPackage, revisited
- From: Carl Woll <carlw@wolfram.com>
- Re: Re: Second argument of BeginPackage, revisited