Exposing Symbols to $ContextPath

江枫思渺然 提交于 2019-12-04 08:10:28

问题


There are a variety of Internal`context functions that are useful, such as InheritedBlock, Bag and StuffBag, etc., as well as many useful Developer` functions.

I wish to expose a selection of these symbols such that they may be addressed plainly without the context name, but I do not want to expose all of them by adding Internal` and Developer` to $ContextPath.

I could use a proxy symbol such as Bag = Internal`Bag but this is neither clean nor fully correct, since it is a reference, and e.g. attributes are not inherited.

Is there a way to selectively expose the symbols I want, without resorting to the kluge above?


回答1:


This is IMO a very deep and valid question, and judging by the vote count, I am not alone in thinking this. If we had this feature fully supported on the language level, this would give one a whole new way to manipulate the scoping and encapsulation, and would IMO often allow for a cleaner code and better information hiding. This would be similar to from module-name import name1,name2,... in Python.

Perhaps as many of us, I have tried multiple approaches, but all of them seem fragile and incomplete. The worst case is for packages, for which I have no good solution. For the interactive work in the FrontEnd, here is one which might be acceptable. First define a general macro to make the literal substitutions:

ClearAll[withImported];
SetAttributes[withImported, HoldAll];
withImported[importingRules : {(_Symbol ->  _String) ..}, code_] :=
  With @@ Join[
     Hold[importingRules] /.
      (name_Symbol -> context_String) :>
          With[{eval =
               Block[{$ContextPath = Append[$ContextPath, context]},
                 ToExpression[context <> ToString[Unevaluated@name]]
               ]},
             Set[name, eval] /; True],
     Hold[code]];

withImported[importingRules : {({__Symbol} -> _String) ..}, code_] :=  
    Reverse[Hold @@ Flatten[Unevaluated[importingRules] /.
        ({syms__Symbol} -> s_String) :> Thread[s :> {syms}]], {2}] /. 
        RuleDelayed -> Rule /.
        Hold[expandedRules : ((_Symbol ->  _String) ..)] :> 
             withImported[{expandedRules}, code];

Then, create a function which would incorporate your favorite shortcuts, for example:

shortcutF = 
   Function[code,
     withImported[
       {
         {PackedArrayQ, ToPackedArray, FromPackedArray} -> "Developer`",
         {InheritedBlock, WithLocalSettings} -> "Internal`"
       },
       code
     ],
     HoldAll];

You can now wrap your code in shortcutF and start using the short names. Up to now, this would also work for packages, but you will have to wrap all your code (or at least those pieces which contain short-cuts) in shortcutF, which is not very convenient. As a further convenience step, you may assign the above function to $Pre:

$Pre = shortcutF;

Here are some examples of use:

In[31]:= 
WithLocalSettings[Null,Abort[],Print["Cleanup"]]

During evaluation of In[31]:= Cleanup
Out[31]= $Aborted[]

In[32]:= PackedArrayQ[Range[10]]
Out[32]= True

In[33]:= PackedArrayQ@FromPackedArray[Range[10]]
Out[33]= False

Since With is used under the cover, what really happens is that your short-cut symbols get substituted by fully-qualified symbol names, before the code is executed.

This is as far as I could get, but this feature seems to be particularly crying for a native support from the language.




回答2:


A variation of Leonid's answer which applies on an earlier stage:

InternalSymbols={"Bag","BagLength","BagPart","StuffBag"}
$PreRead=#/.(InternalSymbols/.{s_String:>s->"Internal`"<>s})&

After typing this in a notebook, typing

?Bag

gives me

Internal`Bag
Attributes[Internal`Bag]={Protected}

while

?AbsSquare

gives

Information::notfound: Symbol AbsSquare not found.

but

?Internal`AbsSquare

gives

Internal`AbsSquare
Attributes[Internal`AbsSquare]={Listable,NumericFunction,Protected}

However it seems to only work in the notebook interface, not when using math on the command line.



来源:https://stackoverflow.com/questions/7912984/exposing-symbols-to-contextpath

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!