# Name scope confusion

Sorry for the too ambiguous title.

First consider a following code snippet.

x = "x"; y = "y";

kk[] := Module[ {q, w, m},
q[a_] := a + 1;
w[a_] := a^2;
m[Globalx] = q;
m[Globaly] = w;
m
]


With this function kk I can write code like this,

kk[][x][1]    (* output -> 2 *)
kk[][y][2]    (* output -> 4 *)


as expected.

However, I want to change the name of the global variables x and y to those of the local variables q and w. Thus, consider a below snippet.

q = "x"; w = "y";

kk2[] := Module[ {q, w, m},
q[a_] := a + 1;
w[a_] := a^2;
m[Globalq] = q;
m[Globalw] = w;
m
]


Note that the only change to the above code is the global variable names x and y. However, this function kk2 does not work as expected anymore. Can you explain?

The output I got was,

kk2[][q][1] (* unevaluated *)
kk2[][w][2]


EDIT: add [] to each kk2 calls as pointed by m_goldberg

-
What exactly are you trying to accomplish with such constructs? This "feels" like trying to do something that has a better solution. In any case, do Module[{q}, Globalq] and observe the result... – ciao Apr 11 '14 at 9:06
@rasher I tried your suggestion. It returns local q instead of global one. Can I ask you why? – Sungmin Apr 11 '14 at 9:13
Search documentation for "Modularity", first hit has a tutorial that might help you understand. Also read the "common pitfalls" question at this site. And again, always good to include in your question what you're trying to accomplish (and why in this case). Most times trying to use global state locally pulling it into a function raises eyebrows... – ciao Apr 11 '14 at 10:26
Also try Module[{q}, Context[q]], which gives Global . That may be confusing, as q is of course supposed to be used as a local variable. But Module resolves naming conflicts by giving q a unique name, rather than by putting q in another context, or something like that. If you want to refer to the "global" q, you can do something like Symbol["q"], but you probably shouldn't. – Jacob Akkerboom Apr 11 '14 at 13:30
kk[x][1] and kk[y][2] don't evaluate. Should they not be kk[][x][1] and kk[][y][2]? – m_goldberg Apr 11 '14 at 13:33

Module works different than scoping constructs in other languages.

Here's a simpler example which already gives a clue of what happens:

x=3; Module[{x}, {x, Globalx, Context[x]}]
(*
==> {x$81, x$81, Global}
*)


You see, no matter whether you prefix it with Global, x gets replaced with x$81, which indeed also has global context. Indeed, this is how Module works: 1. The parsing code generates references to the symbol Globalx whenever you refer to x with or without Global prefix (this is assuming you didn't use any commands changing the current context, of course). Note that symbol resolution already happens at this step. 2. When the Module statement is executed, each instance of Globalx occurring lexically in the expression is replaced with a new variable, here x$81 (the exact name varies from call to call, guaranteeing that the name is unique). So technically, there's not a new scope introduced, but a variable replacement happens.
3. Now the code with the replaced variable is executed.
4. If no references to the introduced "local" variables remain, they are removed again.

You can also see this in action by explicitly constructing the variable name:

x=3; Module[{x}, Symbol["x"]]
(*
==> 3
*)


Here, at the time Module does symbol replacement, the expression doesn't yet contain the symbolGlobalx, but only the expression Symbol["x"] where the "x" is just a string. Therefore the replacement step doesn't replace anything, and during evaluation Symbol["x"] creates a reference to Globalx, not to Globalx\$81 (or whatever the "local" variable is called this time). And since Globalx has been assigned the value 3, it evaluates to that value.

-
Nice answer. +1 – Mr.Wizard Apr 12 '14 at 5:06

I am quite unable to understand why you just don't write

kk[q][a_] := a + 1
kk[w][a_] := a^2


This gives

{kk[q][1], kk[w][2]}

{2, 4}


Wouldn't the above satisfy your needs?

-
Could you read this post mathematica.stackexchange.com/questions/45916/… ? This is the underlying reason I tried this approach. – Sungmin Apr 12 '14 at 3:05

This seems to work.

 q = "x"; w = "y";
kk[] := Module[{q, w, m},
q[a_] := a + 1;
w[a_] := a^2;
m[Symbol["q"]] = q;
m[Symbol["w"]] = w;
m]


Cant imagine why you'd want to do this though.

-
Could you read this post mathematica.stackexchange.com/questions/45916/… ? This is the underlying reason I tried this approach – Sungmin Apr 12 '14 at 3:06