【问题标题】:Exposing Symbols to $ContextPath向 $ContextPath 公开符号
【发布时间】:2011-12-16 07:30:26
【问题描述】:

有多种有用的Internal`context函数,如InheritedBlockBag and StuffBag等,还有很多有用的Developer`函数。

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

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

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

【问题讨论】:

  • +1 在Internal` Developer` 中有很多有用的隐藏函数。你可以编写一个包装函数来实现你的 kludge 属性等......
  • @Simon,是的,我可以,但即使这样通常也没有必要,因为头部首先评估。这本身并不是一个真正的问题,但不知何故它似乎不正确。
  • 相当令人惊讶的是,不使用Unprotect 或类似工具,可以使用Context[symbol] = "context`" 重新定义System` Internal` 符号的上下文。但是,这会将符号从其原始上下文中删除,这是不可接受的。有没有办法给一个符号分配两个不同的上下文?
  • 只是记录历史i.stack.imgur.com/3ODWy.png
  • @belisarius re:你的问题,这很可能是处理这个问题的最好或唯一的方法。但是,我知道它是一个指针,而不是符号本身,出于某种原因,这让我很困扰。

标签: wolfram-mathematica symbols contextpath


【解决方案1】:

Leonid 答案的变体,适用于早期阶段:

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}

但它似乎只在笔记本界面中有效,在命令行上使用数学时无效。

【讨论】:

  • 虽然在我问这个问题之前我很清楚这种方法,但这是一个有效的答案,所以+1,欢迎来到 StackOverflow。
【解决方案2】:

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

也许我们很多人都尝试过多种方法,但它们似乎都很脆弱和不完整。最坏的情况是包裹,我没有好的解决方案。对于 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 被隐藏使用,真正发生的情况是,在执行代码之前,您的快捷符号被完全限定的符号名称替换。

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

【讨论】:

  • 谢谢列昂尼德。请提醒我:你有没有找到一个在解析之前起作用的内核钩子,比如前端的 CellEvaluationFunction?将包的主体封装在字符串中是否可行,使其以parsefunction = ...body = " ... "ToExpression@parsefunction@body 开头?
  • @Mr.Wizard 我不知道这种钩子,唉。至于在这种情况下使用字符串的实用性,这可能取决于具体情况,但我认为这并不是一个普遍好的解决方案。我认为我们确实需要对您要求的特定功能的语言支持,或者可编程阅读器/解析器(这会更好)。
猜你喜欢
  • 2011-01-19
  • 2019-05-16
  • 1970-01-01
  • 2021-09-08
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 2010-09-21
相关资源
最近更新 更多