23

有用的Internal`上下文函数有很多,如InheritedBlockBagStuffBag等,还有很多有用的Developer`函数。

我希望公开这些符号的选择,以便可以在没有上下文名称的情况下简单地处理它们,但我不想通过添加Internal`Developer`来公开所有这些符号$ContextPath

我可以使用代理符号,例如,Bag = Internal`Bag但这既不干净也不完全正确,因为它是一个引用,并且例如属性不是继承的。

有没有办法选择性地公开我想要的符号,而不求助于上面的 kluge?

4

2 回答 2

12

这是 IMO 一个非常深刻和有效的问题,从票数来看,我并不是唯一一个这样想的人。如果我们在语言级别上完全支持此功能,这将提供一种全新的方式来操作范围和封装,并且 IMO 通常会允许更清晰的代码和更好的信息隐藏。这将类似于from module-name import name1,name2,...在 Python 中。

也许和我们中的许多人一样,我尝试过多种方法,但它们似乎都很脆弱和不完整。最坏的情况是包裹,对此我没有好的解决方案。对于 FrontEnd 中的交互工作,这是可以接受的。首先定义一个通用宏来进行文字替换:

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];

然后,创建一个包含您喜欢的快捷方式的函数,例如:

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

您现在可以包装您的代码shortcutF并开始使用短名称。到目前为止,这也适用于包,但是您必须将所有代码(或至少包含快捷方式的那些部分)包装在 中shortcutF,这不是很方便。作为进一步的便利步骤,您可以将上述功能分配给$Pre

$Pre = shortcutF;

以下是一些使用示例:

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

由于With在幕后使用,真正发生的是在执行代码之前,您的快捷符号被完全限定的符号名称替换。

这是我所能得到的,但这个功能似乎特别需要语言的原生支持。

于 2011-11-05T01:06:11.110 回答
5

列昂尼德答案的变体,适用于早期阶段:

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

在笔记本上输入此内容后,输入

?Bag

给我

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

尽管

?AbsSquare

Information::notfound: Symbol AbsSquare not found.

?Internal`AbsSquare

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

然而,它似乎只适用于笔记本界面,而不是在命令行上使用数学时。

于 2011-11-06T15:21:52.407 回答