Moving contexts with $NewSymbol in Mathematica - wolfram-mathematica

I was playing around with $NewSymbol trying to find something to answer this question with. The docs say that
$NewSymbol is applied before the
symbol is actually created. If the
action of $NewSymbol causes the symbol
to be created, perhaps in a different
context, then the symbol as created
will be the one used.
So I tried to automatically move a particular new symbol into a test context which should prevent its creation in the Global`* context, but the symbol gets created in both contexts.
In[1]:= Remove["Global`*"]
In[2]:= $NewSymbol=(Print[#1," : ",#2];
If[#1==="aLongTestSymbolName"&&#2==="Global`",
Symbol["TestContext`"<>#1]])&;
In[3]:= x
During evaluation of In[3]:= x : Global`
Out[3]= x
In[4]:= aLongTestSymbolName
During evaluation of In[4]:= aLongTestSymbolName : Global`
During evaluation of In[4]:= aLongTestSymbolName : TestContext`
Out[4]= aLongTestSymbolName
In[5]:= Names["Global`*"]
Out[5]= {aLongTestSymbolName,x}
In[6]:= Names["TestContext`*"]
Out[6]= {TestContext`aLongTestSymbolName}
I believe that "aLongTestSymbolName" should not be in the Global` context.
Can anyone see what I've done wrong or if I've misinterpreted the documentation?
Note: Having the symbol created in both contexts is not an option for the automatic highlighting in the above linked to question. The idea is to reserve certain symbol names such as "x"~~___ for variables and "f"~~___ for functions and then use string patterns in $NewSymbol to move the symbols to the appropriate highlighted context.

That is because you passed the symbol name to Print, which immediately made the symbol in Global`. :-)
Or not. I should really try things before answering, but I thought I knew this one. Oops.
It seems to me now that $NewSymbol does not intercept the creation of a symbol, or if it does, how to make use of that is not clear.
If one uses:
$NewSymbol = Print["Name: ", #2, #] &;
then:
In[10]:= aNewSymbol
During evaluation of In[10]:= Name: Global`aNewSymbol
Out[10]= aNewSymbol
We see that $NewSymbol does not work like $PrePrint in that its output does not become the expression.
Therefore, if we use:
$NewSymbol = Symbol["TestContext`" <> #] &;
aSecondSymbol
aSecondSymbol is merrily created in Global` as though nothing had changed.
If $NewSymbol can be used to direct the context in which the symbol is created, as the documentation states, it is not clear to me how this may be done.

In this Mathematica Journal article about context issues you may find that just the presence of a new symbol in the parsing phase of the evaluation will add this symbol to the current context. In this case aLongTestSymbolName is handed to the Print and If as #1 and is therefore created in the current context Global`. I don't think there is anything you can do in the $NewSymbol function to prevent this.
The article mentions that even if you use Begin["Context1`"]; someSymbol; End[] someSymbol is not placed in the Context1` context unless Begin["Context1`"] is evaluated on a separate line.

Related

Difference between Clear and Remove in Mathematica

In Mathematica, the documentation for ClearAll states:
ClearAll[symb1, symb2, ...]
clears values, definitions, attributes, messages, and defaults with symbols.
It also supports a similar format where it can clear any values / definitions which match an input string pattern:
ClearAll["form1", "form2", ...]
But there's also the function Remove, for which the documentation says:
Remove[symbol1, ...]
removes symbols completely, so that their names are no longer recognized by Mathematica.
It also supports the same pattern based string input that ClearAll supports.
To me, it seems like both functions accomplish the same exact thing. Is there any practical difference to using one or the other?
I know that if I give an attribute to a symbol, Clear won't remove it but ClearAll and Remove will. But it seems like Remove and ClearAll are doing the same thing.
ClearAll leaves the symbol in the symbol table:
In[1]:= x=7;
In[2]:= ?x
Global`x
x = 7
In[3]:= ClearAll[x]
In[4]:= ?x
Global`x
Remove removes it from the symbol table:
In[5]:= Remove[x]
In[6]:= ?x
Information::notfound: Symbol x not found.
One reason to use Remove instead of ClearAll is if a symbol hides another symbol further down your $ContextPath. Here's a contrived example:
In[1]:= $ContextPath = { "Global`", "System`" };
In[2]:= Global`Sin[x_] := "hello"
Sin::shdw: Symbol Sin appears in multiple contexts {Global`, System`}
; definitions in context Global`
may shadow or be shadowed by other definitions.
In[3]:= Sin[1.0]
Out[3]= hello
In[4]:= ClearAll[Sin]
In[5]:= Sin[1.0]
Out[5]= Sin[1.]
In[6]:= Remove[Sin]
In[7]:= Sin[1.0]
Out[7]= 0.841471
Another reason to use Remove is that the notebook interface only includes known symbols when you choose Edit > Complete Selection (or on a Mac, press Command-K).

How to globally turn off shadowing messages (symbol::shdw)? Or any other 'good practice' suggestions?

I have the following situation:
On[t::shdw]
Message[t::shdw,"t","Foobar","Dork"]
-> t::shdw: Symbol t appears in multiple contexts Foobar; definitions in context Dork may shadow or be shadowed by other definitions. >>
Off[t::shdw]
Message[t::shdw,"t","Foobar","Dork"]
-> **No Warning**
<<MASStoolbox`
-> t::shdw: Symbol t appears in multiple contexts {MASStoolbox`MASS`,Global`}; definitions in context MASStoolbox`MASS` may shadow or be shadowed by other definitions. >>
How can that be? Does On and Off only affect the current Notebook and have no effect when loading packages? If so, how can one get rid of messages like these? How should shadowing errors be treated?
The reason for what you observed is that the statement Off[t::shdw] disables a shadowing message for the symbol t that is currently on the $ContextPath, but not for another t, created during the loading of another package. You should disable shadowing message for that second t, if you don't want to see it. Here is an example:
In[1]:= Off[Test1`a::shdw]
In[2]:=
BeginPackage["Test`"]
a
EndPackage[]
Out[2]= Test`
Out[3]= a
In[5]:= BeginPackage["Test1`"]
a
EndPackage[]
Out[5]= Test1`
Out[6]= a
Here, no message was generated.
Generally, however, I would not want to disable shadowing messages, since shadowing is a serious problem. Shadowing simply means that there is more than one context currently on the symbol search path ($ContextPath), containing symbol(s) with the same (short) name. Basically, if symbol is shadowed, and you refer to it by its short name (that is, symbol without its containing package), you have no guarantee which of the several symbols with the same short name will actually be used. So, the correct way to deal with this is to avoid shadowing altogether, which is always possible, if not always convenient.
The simplest way to avoid shadowing is to load the package you need into the private section of your package, which starts after the line Begin["`Private`"]. You do that by calling Needs[your-package], as always. In this way, the context of the loaded package does not stay on the $ContextPath together with your package's context. The worst case is when you need to load two packages with conflicting symbols. One way out is to construct a wrapper package for one of them, which would load that one privately and rename the conflicting symbols. This may be inconvenient though, since you'd have to rename all functions in a package, even those that don't conflict. Here is an example of a more flexible variant:
First package:
BeginPackage["Test`"];
g[x_?NumericQ] := x^2;
EndPackage[];
Second package:
BeginPackage["Test1`"];
g[x_?NumericQ] := x^3;
EndPackage[]
Main package:
BeginPackage["Main`"];
f::usage = "A test function of a single argument";
Begin["`Private`"];
Block[{$ContextPath = $ContextPath},
Needs["Test`"];
(* Define first delegate private function *)
g1 = Symbol["g"]];
Block[{$ContextPath = $ContextPath},
Needs["Test1`"];
(* Define second delegate private function *)
g2 = Symbol["g"];
];
f[x_] := g1[x]*g2[x]
End[]
EndPackage[]
Now, provided that the system knows where to find your packages:
In[2]:= Needs["Main`"]
In[3]:= f[x]
Out[3]= Test`g[x] Test1`g[x]
In[4]:= f[2]
Out[4]= 32
And we used two conflicting symbols for the same public function. Using Block above served to localize the code where the first or second definition of g is used. Note that there is some inconvenience with this method in that we need to use Symbol["your-symbol-name"], to delay the parsing until run-time.
A much simple method is to just refer to symbols by their long names. In the above, we could just use Test`g and Test1`g and then there is no need for the heavy machinery. This is somewhat less flexible however, since you have to "hard-code" the symbol's context into the code.
You can overload Message to turn it off:
Unprotect#Message;
Message[MessageName[s_, "shdw"],___] := Null;
Protect#Message;
This code also emits a more helpful and correct message, and it verifies its assertions with Assert:
Unprotect#Message;
Message[MessageName[s_, "shdw"],
rest : PatternSequence[snHeld_, pathsHeld_, newpath_]] :=
With[{paths = ReleaseHold#pathsHeld},
{memberpaths = Select[$ContextPath, MemberQ[paths, #] &],
sn = ReleaseHold#snHeld},
Print#StringTemplate[
"Note: Symbol `` added in context ``, so that it now appears in \
multiple contexts: ``. On the context path, it is currently found in: \
``. Definitions in the first context of the context path, ``, will \
shadow any other definitions."][sn, newpath, paths, memberpaths,
First#memberpaths];
(*symbol name*)
Assert[SymbolName#s === sn];
(*demonstrate that First#
memberpaths is the context used for short names*)
Assert[ToExpression#StringTemplate[
"Unevaluated#`` === Unevaluated#````"
][sn, First#memberpaths, sn
]
];
(*and not any other context*)
Assert#AllTrue[TrueQ][ToExpression#StringTemplate[
"Unevaluated#`` =!= Unevaluated#````"
][sn, #, sn
] & /# DeleteCases[paths, First#memberpaths]
];
];
Protect#Message;
Try:
Global`Image
Note: Symbol Image added in context Global`, so that it now appears in multiple contexts: {Global`, System`}. On the context path, it is currently found in: {System`, Global`}. Definitions in the first context of the context path, System`, will shadow any other definitions.
c.f. https://mathematica.stackexchange.com/questions/43381/result-about-context-is-inconsistent-with-the-description-of-power-programming/119887#119887

Is it possible to delete "context`" from the list of loaded Contexts[]?

We can remove all symbols in a particular context by using Remove["context`*"]. But is it possible to remove "context`" itself from the system so that it will no longer be listed in Contexts[]?
As far as I can tell (a guess), a context is automatically removed from Contexts[] once it becomes empty (has no symbols). At least, this happens in my tests. Here is one:
In[1]:=
BeginPackage["Test`"]
EndPackage[]
Out[1]= Test`
In[3]:= MemberQ[Contexts[],"Test`"]
Out[3]= False
In[4]:= Test`a
Out[4]= a
In[5]:= MemberQ[Contexts[],"Test`"]
Out[5]= True
In[6]:= Remove["Test`*"]
In[7]:= MemberQ[Contexts[],"Test`"]
Out[7]= False
This may also explain why calling Contexts[] takes a sizable fraction of a second - the system must check for every context whether or not it is empty. Anyways, the answer to your question seems simple - remove all symbols and the context will be removed from Contexts[]. This also works for contexts loaded by the system - you may try some (XML' for example), although needless to say this is not a good practice, to say the least.

Overloading Set[a, b] (a = b)

I would like to overload Mathematica's Set function (=), which turns out to be too tricky for me (see following code example). I successfully overloaded other functions (e.g. Reverse in the code example). Any suggestions?
In[17]:= ClearAll[struct];
In[18]:= var1=struct[{1,2}]
Out[18]= struct[{1,2}]
In[19]:= Reverse#var1
Out[19]= struct[{1,2}]
In[20]:= Head[var1]
Out[20]= struct
In[21]:= struct/:Reverse[stuff_struct]:=struct[Reverse#stuff[[1]]]
In[22]:= Reverse#var1
Out[22]= struct[{2,1}]
In[23]:= struct/:Set[stuff_struct,rhs_]:=Set[struct[[1]],rhs]
In[24]:= var1="Success!"
Out[24]= Success!
In[25]:= var1
Out[25]= Success!
In[26]:= Head[var1]
Out[26]= String
In[27]:= ??struct
Global`struct
Reverse[stuff_struct]^:=struct[Reverse[stuff[[1]]]]
(stuff_struct=rhs_)^:=struct[[1]]=rhs
I don't think that what you want can be done with UpValues (alas), since the symbol (tag) must be not deeper than level one for definition to work. Also, the semantics you want is somewhat unusual in Mathematica, since most Mathematica expressions are immutable (not L-values), and their parts can not be assigned values. I believe that this code will do something similar to what you want:
Unprotect[Set];
Set[var_Symbol, rhs_] /;
MatchQ[Hold[var] /. OwnValues[var], Hold[_struct]] := Set[var[[1]], rhs];
Protect[Set];
For example:
In[33]:= var1 = struct[{1, 2}]
Out[33]= struct[{1, 2}]
In[34]:= var1 = "Success!"
Out[34]= "Success!"
In[35]:= var1
Out[35]= struct["Success!"]
But generally, adding DownValues to such important commands as Set is not recommended since this may corrupt the system in subtle ways.
EDIT
Expanding a bit on why your attempt failed: Mathematica implements flow control and assignment operators using the mechanism of argument holding (Hold* - attributes, described here). This mechanism allows it to, in particular, imitate pass-by-reference semantics needed for assignments. But then, at the moment when you assign to var1, Set does not know what is stored in var1 already, since it only has the symbol var1, not its value. The pattern _struct does not match because, even if the variable already stores some struct, Set only has the variable name. For the match to be successful, the variable inside Set would have to evaluate to its value. But then, the value is immutable and you can not assign to it. The code I suggested tests whether the variable has an assigned value that is of the form struct[something], and if so, modifies the first part (the Part command is an exception, it can modify parts of an L-value expression provided that those parts already exist).
You can read more on the topics of Hold* - attributes and related issues in many places, for example here and here
I also do not believe that this can be done with TagSet, because the first argument of Set must be held.
It seems to me that if modifying Set, it can be done with:
Unprotect[Set]
Set[s_, x_] /; Head[s] === struct := s[[1]] = x
However, Leonid knows Mathematica better than I, and he probably has a good reason for the longer definition.

What is dollar sign $ used for internally?

What is the symbol $ used for internally?
I do not mean the compound forms x$388 or $5 etc., just the $ by itself.
I am wondering if this is a valid object to use in notation, or what I will break if I do.
It is unwise to have user variables that end in an odd number of $ characters (not counting the first character). x$, y$$$, and $$ are all poor choices for variable names.
This is because appending an odd number of $ to an identifier is a technique called "lexical renaming," which the Mathematica kernel uses to avoid conflicts in variable names when higher-order functions return functions that use the same variable names as their parents. This technique is used in a variety of scoping constructs, including Function, Module, With, and Rule; here is an example with Function:
In[1]:= f = Function[{x, y}, Function[{x}, x+y]]
Out[1]= Function[{x, y}, Function[{x}, x + y]]
In[2]:= f[2,3]
Out[2]= Function[{x$}, x$ + 3]
In[3]:= ?*`x$
Global`x$
Attributes[x$] = {Temporary}
In short, appending $ characters is a system-internal renaming mechanism, and identifiers of this form are recognized by Mathematica as "lexically renamed" versions of the $-less forms, with Temporary attribute. It is not recommended to use variables of this form in your own code.
Mathematica is a term-rewriting language that can behave like a lexically scoped functional language by use of internal rewriting mechanisms such as "lexical renaming."
In version 7, symbol System`$
used to be already created in a fresh kernel, but not used for anything as far as I know. In version 8, symbol $ is not pre-created:
In[1]:= Context["$"]
During evaluation of In[1]:= Context::notfound: Symbol $ not found. >>
Out[1]= Context["$"]
I would agree with Szabolcs that code using $ in System context might break in future versions, as well as any other code that modifies System symbols.

Resources