5

Consider the following snippet of code.

Clear[f, g]
f[x_] := Function[{i}, x];
g[h_] := Module[{Z},
   Z[i_] := Print[h];
   Print[h];
   Z[1];
];

When g[f[2]] is called, the first Print correctly returns Function[{i$},2], while the second Print returns an error with Function[{1},2] as the output. The error arises from a conflict between the two local variables i's in f and Z. In general, Mathematica automatically renames variables to avoid conflict, as described here.

Why is there a conflict in this case? Other than choosing an alternative variable name, what are the useful guidelines one should follow to avoid such conflicts?

anon
  • 53
  • 2

2 Answers2

4

Using

SetSystemOptions["StrictLexicalScoping" -> True]

will fix this.

Related (long reading!):

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
  • Also see comment thread under this question. – Szabolcs Apr 02 '15 at 13:47
  • Is "StrictLexicalScoping" documented anywhere? – anon Apr 03 '15 at 00:57
  • @anon I linked to the sources I am aware of. – Szabolcs Apr 03 '15 at 01:13
  • Thank you. In summary, lexical scoping in MMA has flaws, and "StrictLexicalScoping" developed by Daniel Lichtblau at Wolfram attempts to fix these issues. Currently, this method is still under development, and is not perfect. – anon Apr 03 '15 at 01:37
  • Szabolcs, I have been using the template Bug introduced in x.x and fixed in x.x.x for bug headers. If you would be willing to adopt it I think it would make future searches easier. – Mr.Wizard Apr 09 '15 at 15:37
1

EDIT

 SetAttributes[g, HoldFirst]

will solve your conflict here. To make this plausible, look at this line inside of your Module:

 Z[i_]:=Print[h]

Without HoldFirst this will look for the Kernel like:

 Z[i_]:= Print[Function[{i}, 2]]

when h is set to f[2] := Function[{i},2], so the i inside of your functions definition is now by mistake recognizes as the pattern i_, what you dont want. With the Attribute HoldFirst the assignment effectively looks like this:

 Z[i_]:=Print[f[2]]

then in this case, i inside of f[2] is not recognizes as the Pattern i_ and you dont get these conflicts.

Here is the example:

SetAttributes[g, HoldFirst]
g[f[2]]

Out:

Function[{i$},2]

Function[{i$},2]
sacratus
  • 1,556
  • 10
  • 18