# Variable assignment/replacement issues

I have three questions about variable assignment.

Module[{z},
z = y;
p'[y] /. p -> Function[y, Evaluate[z]]]


When I run the above code, it outputs 0.

1) If I run the same code outside the Module, it gives me 1. Why isn't the local z treated like the global case (which I can understand)?

2) If I remove the call to Evaluate (and run without the module), it again gives me 0. When does Mathematica replace the symbol z with y, the definition I gave, and when not?

It's especially confusing that I have to be global and evaluate, when other times the replacement seems even more aggressive:

fn[x_] := Module[{}, x = 1; x]
fn[2]


This gives me an error, Cannot assign to raw object 2, because it's gone and replaced the symbol x with the value I passed, no evaluate, no global, nothing.

3) What's the difference in this case?

This seems to come up again and again in different ways, and always comes back to the same unclear replacement/assignment rules. It just ends up being complete guesswork for me. Why do the assignment rules seem so much more arbitrary and less clear than in other languages?

• There's renaming happening behind the scenes, resulting in Function[y\$, y], whose derivative is indeed 0. Use TracePrint[] to see what's happening in detail. Also, try Module[{z}, z = y; p'[y] /. p -> Function[Evaluate[y], Evaluate[z]]]. – J. M. is away May 20 '17 at 17:38