# Treat all variables as local in a module [duplicate]

In most languages, any variable defined inside a function is considered local.

# a Python function
def toRomanNumerals(num):
digits = # ...
string = ''
while num > 0:
(value, letters) = # ...
string = # ....
return string


In a Mathematica Module, however, we must specify a list of all variables to treat as local.

toRomanNumerals[i_Integer?Positive] :=
Module[{num = i, string = "", value, letters, digits},
digits = (* ... *);
While[num > 0, {value, letters} =
(* ... *);
string = (* ... *).];
string]


I sometimes find it tedious to manually type the list of all local variables. Do others feel the same way?

Is there a way to create a Module which treats all symbols defined inside as local?

-

## marked as duplicate by Michael E2, Sjoerd C. de Vries, bobthechemist, rm -rf♦Jan 18 at 6:01

There is a big difference between Python of Mathematica (one of many): Mathematica is a symbolic language where a symbol may hang around without having any value, and this is perfectly legal. In Python, it is clear which symbols to treat as local: all currently unbound symbols. But In Mathematica, this is not necessarily the case. You can implement Python-style bindings using macros, but then you will have to adopt the same constraint, that by local you want to consider all currently unbound variables. –  Leonid Shifrin Nov 27 '13 at 20:18
To give an example in the spirit of Leonid's comment: Module[{}, f[x]]. Should f and x be local or global? Perhaps you say that f is global if f has associated rules ("it's defined"), otherwise local, and the same applies to x. But what if x has a special meaning in the definition of f, but it doesn't have any associated rules of its own? Say, f[big]=1; f[small]=0 where small and big are symbols without definitions, but are used for a specific purpose. Even some builtins like \$Pre don't have a definition by default. –  Szabolcs Nov 27 '13 at 20:25
In most languages, any variable really? What about Ada, Pascal, C, C++, Java, SNOBOL, PLI, COBOL? don't you have to declare variable? I much prefer Mathematica way. It is a form of documentation. One can look at the list of local variable and know which are local or which are not. Languages that do not require declaration are sloppy languages IMNSHO. ofcourse, in Mathematica, you do not have to declare local symbols as local, but this is bad, since they will become global. I think Mathematica got it right here. –  Nasser Nov 27 '13 at 20:27
@Nasser I guess what he means that in languages where you don't need to declare a variable, the variable will typically live in the scope where it's mentioned first; unless it's explicitly made global. Mathematica doesn't require declaration either (you can use any symbol anywhere), but the symbol will be global by default, unless you ask to make it local. –  Szabolcs Nov 27 '13 at 20:36
@Szabolcs but OP said In most languages, any variable declared inside a function is considered local. and I was replying to this. But any way. I myself do not languages that makes things implicit like this. I prefer explicit declarations. Much better in the long run. It helps build better software and better habit to learn to declare something before using it. –  Nasser Nov 27 '13 at 20:44

This sort of programming is not my strength and I don't know Python. Reading the comments, perhaps this won't quite be perfect, but it might be good enough. It seems good enough for many purposes, at least in the way I interpret the question. It localizes all Symbols in the code that are in the "Global" context and don't have Ownvalues or DownValues. If you want to exclude those with UpValues etc., then it should be easy how to modify it to do so.

ClearAll[localizeAll];
SetAttributes[localizeAll, HoldAll];
localizeAll[code_] :=
With[{vars = Join @@ Union @
Cases[Hold[code],
s_Symbol /; Context[s] == "Global" &&
Length@OwnValues[s] == 0 && Length@DownValues[s] == 0 :> Hold[s],
Infinity,
(* Module[{##}, code] & @@ vars *)  (* original *)
vars /. Hold[v___] :> Module[{v}, code] (* Leonid Shifrin's suggestion *)
]


Example:

Clear[z];
z[a_] := a^2;
localizeAll[x = 2; y = x++; z[x] = y; q[r_] := s; z[2x]]
z[3]
z[x]
q[1]

(* 36 *)
(* 2 *)
(* x^2 *)
(* q[1] *)


Note that because z was defined, z[3] got redefined.

I think I might rather take a few seconds and type out the variables explicitly. It might save time in the long run.

-
This looks similar to my code here. An interesting variation. –  rcollyer Nov 28 '13 at 4:32
@rcollyer Yes, the idea is similar. Yours looks more sophisticated, but frankly, I don't have the experience to confidently judge the shortcomings my own code. –  Michael E2 Nov 28 '13 at 5:15
I don't have the time to test right now, but it seems that your code will leak evaluation at the stage Module[{##},body]&@@.... Otherwise, that's also how I would have done that (and actually did a number of times, just can't find my posts on this right now). You can use injector pattern to avoid the leaks: vars/.Hold[x___]:>Module[{x},code] - this is what I usually do in such cases. +1. –  Leonid Shifrin Nov 28 '13 at 12:03
@LeonidShifrin Thanks. I incorporated your suggestion. –  Michael E2 Nov 29 '13 at 3:49