Подтвердить что ты не робот

Отображение символов в $ContextPath

Существуют различные функции контекста Internal`, которые полезны, например InheritedBlock, Bag и StuffBag и т.д., а также множество полезных функций Developer`.

Я хочу показать выбор этих символов таким образом, чтобы они могли быть адресованы явно без имени контекста, но я не хочу раскрывать их все, добавив Internal` и Developer` в $ContextPath.

Я мог бы использовать прокси-символ, например Bag = Internal`Bag, но это не является ни чистым, ни полностью правильным, поскольку он является ссылкой и, например, атрибуты не наследуются.

Есть ли способ выборочно разоблачить символы, которые я хочу, не прибегая к kluge выше?

4b9b3361

Ответ 1

Это ИМО - очень глубокий и правильный вопрос, и, судя по подсчету голосов, я не одинок в этом. Если бы эта функция полностью поддерживалась на языковом уровне, это дало бы совершенно новый способ манипулировать областью охвата и инкапсуляции, и ИМО часто позволяла бы более чистый код и лучшую информацию скрывать. Это было бы похоже на 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[[email protected]]]
               ]},
             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]:= [email protected][Range[10]]
Out[33]= False

Поскольку With используется под обложкой, что действительно происходит, так это то, что ваши короткие символы заменяются полностью квалифицированными именами символов, прежде чем код будет выполнен.

Это насколько я могу получить, но эта функция, похоже, особенно плачет за поддержку на родном языке.

Ответ 2

Вариант ответа Леонида, который применяется на более ранней стадии:

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}

Однако, похоже, он работает только в интерфейсе ноутбука, а не при использовании математики в командной строке.