# Using Solve[ ] inside a Module

I want to use Solve[] inside a Module. If I make the variables solved for local to the module, they are treated differently than if I leave them global. For example,

SolveIt[a_, b_] := Module[{x, soln},
soln = Solve[a x + b == 0, {x}];
Return[soln]
];
SolveIt[3, 4]

returns

{{x$1342 -> -(4/3)}} If I leave x global, the function returns {{x -> -(4/3)}} But if that global x has a value, the Solve[] function says that x is not a valid variable. Could someone please (a) explain what's going on, and (b) suggest best practice for using Solve[] and similar functions within a module. Thanks! • Maybe you can consider using a formal variable? Those are guaranteed to never have anything assigned to them… – J. M. will be back soon Jul 8 '16 at 12:22 • @J.M. Mma formal variables are new to me. I will have to study to see how to use them in this context. Thanks! – Joseph O'Rourke Jul 8 '16 at 13:15 • Just to start you off: SolveIt[a_, b_] := \[FormalX] /. Solve[a \[FormalX] + b == 0, \[FormalX]]. (It looks gnarly on SE, but should paste fine into Mathematica.) – J. M. will be back soon Jul 8 '16 at 13:17 • The problem is that if x has a value, it will evaluate immediately in an expression such as x -> 1. There is just no good way to return something containing x if x has a value. Do you really need to return x from the function (as part of a larger expression)? Or is it sufficient to return the solution as a number, i.e. return val instead of x -> val? – Szabolcs Jul 8 '16 at 21:19 ## 2 Answers Do you really need to return x from your function (even as part of a larger expression)? There is simply no good way to do this if x has a global value, as x = 1; x -> 2 immediately evaluates to 1 -> 2. You could return the solution value only (val instead of x -> val): SolveIt[a_, b_] := Module[{x, soln}, soln = Solve[a x + b == 0, {x}]; x /. soln ] SolveIt[3, 4] (* {-(4/3)} *) Using formal variable were mentioned. These have the advantage that they are Protected, therefore they are guaranteed not to have an assigned value. So you might consider Clear[SolveIt] SolveIt[a_, b_] := \[FormalX] /. Solve[a \[FormalX] + b == 0, \[FormalX]] SolveIt[3, 4] (* {-(4/3)} *) (Note: you can type \[FormalX] using ESC$x ESC.)

But there is a big problem with this. This works fine:

SolveIt[a, 1]
(* {-(1/a)} *)

SolveIt[\[FormalX], 1]
(* {-I, I} *)

We passed a symbol into the function, and that symbol happened to be already in use internally ... so we're solving the equation x^2 + 1 == 0 now (compare to a x + 1 ==0 before).

The same problem appears with Block:

Clear[SolveIt]
SolveIt[a_, b_] :=
Block[{x, soln},
soln = Solve[a x + b == 0, {x}];
x /. soln
];

SolveIt[y, 1]
(* {-(1/y)} *)

SolveIt[x, 1]
(* {-I, I} *)

Thus it is important to use Module (and not Block or a formal variable) if you want to make it possible to pass symbols into the function. If you only pass in numbers, this is not a problem, but then you may consider defining the function as SolveIt[a_?NumericQ, b_?NumericQ].

In case you are not certain about the difference between Module and Block, see here:

In short, both localize variables, but Module does this by renaming them to a unique name (so that x becomes something like x$123) while Block just temporarily removed any definitions that may be associated with x (but x is still the same symbol as before). Module emulates lexical scoping and Block does dynamic scoping. • Thank you! Indeed, "it [is] sufficient to return the solution as a number." – Joseph O'Rourke Jul 8 '16 at 22:13 As explained in Mathematica help, "Module creates a symbol with name xxx\$nnn to represent a local variable with name xxx. The number nnn is the current value of \$ModuleNumber." This variable is not renamed after the module has completed.

If instead the variable x refers to a global variable which already has a value (e.g. x=3), the x in Solve[eqn,x] will be evaluated, so that it becomes Solve[eqn,3] (leading to the message Solve::ivar: 3 is not a valid variable.

@J.M. suggests the use of formal variables which (I think) are intended for precisely this sort of use case.

SolveIt[a_, b_] := Solve[a \[FormalX] + b == 0, \[FormalX]]]