wolfram mathematica - Exponiendo los símbolos a $ ContextPath
wolfram-mathematica symbols (2)
Hay una variedad de funciones de contexto Internal`
que son útiles, como InheritedBlock
, Bag
and StuffBag
, etc., así como muchas funciones útiles para Developer`
.
Deseo exponer una selección de estos símbolos de modo que puedan abordarse claramente sin el nombre de contexto, pero no quiero exponerlos todos agregando Internal`
y Developer`
a $ContextPath
.
Podría usar un símbolo proxy como Bag = Internal`Bag
pero esto no es limpio ni totalmente correcto, ya que es una referencia y, por ejemplo, los atributos no se heredan.
¿Hay una manera de exponer selectivamente los símbolos que quiero, sin recurrir al kluge anterior?
Esta es una pregunta muy profunda y válida de la OMI, y a juzgar por el recuento de votos, no estoy solo en esto. Si tuviéramos esta función totalmente compatible en el nivel de idioma, esto le brindaría a una forma completamente nueva de manipular el alcance y la encapsulación, y IMO a menudo permitiría un código más limpio y una mejor ocultación de la información. Esto sería similar a from module-name import name1,name2,...
en Python.
Tal vez como muchos de nosotros, he intentado múltiples enfoques, pero todos parecen frágiles e incompletos. El peor de los casos es para paquetes, para los cuales no tengo una buena solución. Para el trabajo interactivo en FrontEnd, aquí hay uno que podría ser aceptable. Primero define una macro general para hacer las sustituciones literales:
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];
Luego, cree una función que incorpore sus accesos directos favoritos, por ejemplo:
shortcutF =
Function[code,
withImported[
{
{PackedArrayQ, ToPackedArray, FromPackedArray} -> "Developer`",
{InheritedBlock, WithLocalSettings} -> "Internal`"
},
code
],
HoldAll];
Ahora puede envolver su código en shortcutF
y comenzar a usar los nombres cortos. Hasta ahora, esto también funcionaría con los paquetes, pero tendrá que envolver todo su código (o al menos las piezas que contienen shortcutF
) en shortcutF
, lo cual no es muy conveniente. Como un paso adicional, puede asignar la función anterior a $Pre
:
$Pre = shortcutF;
Aquí hay algunos ejemplos de uso:
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
Ya que With
se usa debajo de la cubierta, lo que realmente sucede es que sus símbolos de atajo se sustituyen por nombres de símbolos completamente calificados, antes de que se ejecute el código.
Esto es todo lo que pude conseguir, pero esta característica parece ser particularmente el llanto de un soporte nativo del idioma.
Una variación de la respuesta de Leonid que se aplica en una etapa anterior:
InternalSymbols={"Bag","BagLength","BagPart","StuffBag"}
$PreRead=#/.(InternalSymbols/.{s_String:>s->"Internal`"<>s})&
Después de escribir esto en un cuaderno, escribiendo
?Bag
me da
Internal`Bag
Attributes[Internal`Bag]={Protected}
mientras
?AbsSquare
da
Information::notfound: Symbol AbsSquare not found.
pero
?Internal`AbsSquare
da
Internal`AbsSquare
Attributes[Internal`AbsSquare]={Listable,NumericFunction,Protected}
Sin embargo, parece que solo funciona en la interfaz del portátil, no cuando se usan las matemáticas en la línea de comandos.