Re: Re: Second argument of BeginPackage, revisited
- To: mathgroup at smc.vnet.net
- Subject: [mg78546] Re: [mg78537] Re: Second argument of BeginPackage, revisited
- From: Carl Woll <carlw at wolfram.com>
- Date: Wed, 4 Jul 2007 05:29:07 -0400 (EDT)
- References: <f5td66$36j$1@smc.vnet.net><f62k72$bod$1@smc.vnet.net> <200707031051.GAA02603@smc.vnet.net>
Andrew Moylan wrote: >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`"] > > An alternative is to use BeginPackage["a`", {"PhysicalConstants`", "Units`"}] Carl Woll Wolfram Research > > >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. >>> >>> > > > >
- References:
- Re: Second argument of BeginPackage, revisited
- From: Andrew Moylan <andrew.j.moylan@gmail.com>
- Re: Second argument of BeginPackage, revisited