5
$\begingroup$

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?

$\endgroup$
  • $\begingroup$ The problem is that MMA thinks there is no conflict, right? $\endgroup$ – Kuba Apr 2 '15 at 9:04
  • $\begingroup$ Yes, but I don't understand why. $\endgroup$ – anon Apr 2 '15 at 9:12
  • $\begingroup$ Not so much related but this is a nice topic about understanding of scoping in mma 75323 $\endgroup$ – Kuba Apr 2 '15 at 9:35
4
$\begingroup$

Using

SetSystemOptions["StrictLexicalScoping" -> True]

will fix this.

Related (long reading!):

$\endgroup$
  • $\begingroup$ Also see comment thread under this question. $\endgroup$ – Szabolcs Apr 2 '15 at 13:47
  • $\begingroup$ Is "StrictLexicalScoping" documented anywhere? $\endgroup$ – anon Apr 3 '15 at 0:57
  • $\begingroup$ @anon I linked to the sources I am aware of. $\endgroup$ – Szabolcs Apr 3 '15 at 1:13
  • $\begingroup$ 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. $\endgroup$ – anon Apr 3 '15 at 1:37
  • $\begingroup$ 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. $\endgroup$ – Mr.Wizard Apr 9 '15 at 15:37
1
$\begingroup$

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]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.