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$
3
  • $\begingroup$ The problem is that MMA thinks there is no conflict, right? $\endgroup$
    – Kuba
    Apr 2, 2015 at 9:04
  • $\begingroup$ Yes, but I don't understand why. $\endgroup$
    – anon
    Apr 2, 2015 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, 2015 at 9:35

2 Answers 2

4
$\begingroup$

Using

SetSystemOptions["StrictLexicalScoping" -> True]

will fix this.

Related (long reading!):

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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