在我看来,这是一个非常深刻和有效的问题,从投票数来看,我并不是唯一一个这么想的人。如果我们在语言级别上完全支持此功能,这将提供一种全新的方式来操作范围和封装,并且 IMO 通常会允许更清晰的代码和更好的信息隐藏。这类似于from module-name import name1,name2,...
在Python中。
也许和我们许多人一样,我尝试过多种方法,但所有这些方法似乎都很脆弱且不完整。最坏的情况是对于包,对此我没有很好的解决方案。对于前端的交互工作,这里是一个可能可以接受的。首先定义一个通用宏来进行文字替换:
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
Since With
在幕后使用,真正发生的是在执行代码之前,您的快捷符号被完全限定的符号名称替换。
这是我所能得到的,但这个功能似乎特别需要该语言的本地支持。