这是 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
在幕后使用,真正发生的是在执行代码之前,您的快捷符号被完全限定的符号名称替换。
这是我所能得到的,但这个功能似乎特别需要语言的原生支持。