Contents:
Purpose of codes below
Method 1: Create a new context
Method 2: Turn the variables to strings
Method 3: Localize all variables and use Format
Purpose of codes below
Below are some possibilities that try to avoid using tedious code each time one wants to use symbolic computations with predefined variables. That is, the purpose of the codes below is to avoid having to use multiple functions such as Hold, HoldForm (like Hold without the wrapper), Block, Module and most importantly avoiding the tedious task of having to specify which variables need to be hidden from their definitions.
Method 1 : Create a new context.
Advantage: Make multiple symbolic computations in multiple cells while the context is activated.
Risk: Forgetting to leave the context or having to make a keyboard shortcut that makes context opening and context closing cells. Error messages of shadowing are shown each time. If we use Quiet then there is the risk that errors we do not want will not be seen.
Tedious part: One has to make 2 other cells with function calls BeginLocal[](defined below) and EndLocal[](defined below) before writing what we want. Also context errors will appear each time. Finally we have to remember to evaluate EndLocal[] once we are done.
The answer here provides one way to use symbolic calculations with predefined variables. The tedious and maybe dangerous part with that method is that one has to do 3 steps:
1: Evaluate the function BeginLocal[] (defined below) in one cell
2: The code you wanted to use in another cell
3: Evaluate the function EndLocal[] (defined below) in another cell
There is maybe a risk here that the user will forget to use EndLocal[]. One should probably make both the BeginLocal[] and EndLocal[] cells before writing the code for an expression we want to manipulate and then we have to evaluate EndLocal[] at the end. Perhaps this could be made easier with keyboard shortcuts. Search stack exchange for methods to create keyboard shortcuts.
The code from that answer:
Module[{isEx, conlst},
BeginLocal[] := Module[{con}, conlst = $ContextPath;
BeginPackage[SymbolName@con <> "`"];];
System`EndLocal[] :=
If[ValueQ@conlst, EndPackage[]; $ContextPath = conlst;
Clear@conlst];]
Example
x=4;y=4;
First input cell:
BeginLocal[]
Second input cell :
Expand[(x^2 + y^2)/x^2]
Third input cell :
EndLocal[]
Method 2: Turn the variables to strings
Advantage: No need to use two functions in two different cells and no context shadowing errors.
Risk: It seems unlikely for how I use Mathematica but maybe one would defined both the variable x and the string "x" in which case the code below will not work.
Tedious part: we have to use the function hide(defined below) like code //hide each time. If we have many symbolic calculations it might be better to use the BeginLocal[] and EndLocal[] functions from the previous method.
The code below is inspired by the answer here:
ClearAll[hide];
SetAttributes[hide, HoldAll];
hide[code_] :=
ReleaseHold@
ReplaceAll[Hold[code],
s_Symbol /; Context[s] == "Global`" :> ToString@Unevaluated@s]
x = 4; y = 4; Expand[(x^2 + y^2)/x^2] // hide
Out: $$ \frac{\text{y}^2}{\text{x}^2}+1 $$
However, although the expression looks like what we wanted, x and y are strings as can be checked using FullForm:
x = 4; y = 4; Expand[(x^2 + y^2)/x^2] // hide // FullForm
Out: Plus[1,Times[Power["x",-2],Power["y",2]]]
Method 3: Use Format
Advantage : No issue with the case where one defines both x and the string "x" as "x" is used only for formatting and same advantage as the previous method.
Tedious part: Same as for the previous method
Using Format was mentioned by @user293787 in the comments.
The code below is inspired by the answer (same as for method 2) here:
ClearAll[hide];
SetAttributes[hide, HoldAll];
hide[code_] :=
Module[{vars, modcode},
(association of the form Hold[variable]->{variable to string,
localized variable (added dollar sign followed by number)})
vars =
Association@
Cases[Hold[code],
s_Symbol /;
Context[s] ==
"Global`" :> (Hold@s -> {ToString@Unevaluated@s,
Unique@Unevaluated@s}), All];
(* modified input code/expression with localized variables *)
modcode =
ReplaceAll[Hold[code],
s_Symbol /; Context[s] == "Global`" :> Last@vars@Hold@s];
(Formating the localized variables to look like the original
variables)
Do[With[{string = First@vars@key},
Format[Last@vars@key] := string], {key, Keys@vars}];
modcode // ReleaseHold
]
Example
x = 4; y = 4; Expand[(x^2 + y^2)/x^2] // hide
Out: $$\frac{\text{y}^2}{\text{x}^2}+1$$
Format, for exampleFormat[xx] = "x"means thatxxwill henceforth print asx, though it remains different from the symbolx. You can (and should!) localize symbols usingModule. – user293787 Oct 26 '22 at 09:12Holdnot feasible? You can always use something likeUnevaulated[...] /. {x->Hold[x], y->Hold[y]}to replace all symbols before evaluation, or evenUnevaluated[...] /. sym:x|y :> Hold[sym]– Lukas Lang Oct 27 '22 at 12:16ModuleandBlock? They are just solving the problem of re-using symbols independently of their values received before. – Alexei Boulbitch Oct 27 '22 at 13:05