Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm completely puzzled by the following codes:

Clear[func, f]
a = x^2 + z;
func[k_] := Block[{f}, (f[x_] := Evaluate[(a /. {z -> k})]; f[1])]
func[2]
2+x^2

But I think it should be 3, i.e., 2+1^2=3.

Actually for the following code:

 f[x_] := Evaluate[(a /. {z -> k})]; f[1]

The output is 3.

Can you explain the evaluation inside the Block?

Taking Simon Woods' advice, for

func[k_] := 
 Block[{f, tmp}, (tmp = Evaluate[a /. z -> k]; f[x_] = tmp; f[1])]

Trace[func[2]]

gives,

{func[2],Block[{f,tmp},tmp = Evaluate[a /. z -> 2],f[x_] = tmp; f[1]],...}

But, for the codes

func[k_] := Block[{f}, (f[x_] = Evaluate[a /. z -> k]; f[1])]
Trace[func[2]]

gives,

{func[2],Block[{f},f[x$_] = Evaluate[a /. z -> 2];f[1],...}

I notice that the arguments of f inside the Block are different in these two cases, and that is the reason.

But why is the difference?

share|improve this question
    
You can do func[k_] := Block[{y = (a /. {z -> k}), f}, (f[x_] = y; f[1])]. –  b.gatessucks Jul 18 '13 at 8:05
    
@b.gatessucks Yes,I've notice this:func[k_] := Block[{f, tmp}, (tmp = Evaluate[a /. z -> k]; f[x_] = tmp; f[1])] But why? –  yulinlinyu Jul 18 '13 at 8:07
1  
Have a look at Trace[func[2]] –  Simon Woods Jul 18 '13 at 8:09
    
@Simon Woods, see my edit, I will appreciate your reply. –  yulinlinyu Jul 18 '13 at 8:49

1 Answer 1

Nested scoping constructs like Module or SetDelayed apply a variable renaming, adding the symbol ($) to each variable. For that, take a look at the internal form of f, as you defined it

func[k_] := Block[{f}, 
                  f[x_] := Evaluate[ReplaceAll[a, {z -> k}]];
                  Information[f];
                  Trace[f[1]]]

func[2]

Global`f
f[x$_]:=2+x^2

{f[1], 2+x^2}

the function f accepts any argument and gives the name x\$ to it. Then goes to evaluate the right-hand side and looks for any occurrence of x\$ so to make the replacement with 1, in that case. Unfortunately, the global variable a (that defined externally) depends on x and not on x$ so no replacement happens. A possible solution is to change the name of the variable x so to avoid confusion and make clear the replacement of such variable inside the ReplaceAll.

func[k_] := Block[{f},
                   f[var_] := Evaluate[ReplaceAll[a, {z -> k, x -> var}]];
                   Information[f];
                   Trace[f[1]]]


func[2]
Global`f
f[var$_]:=2+var$^2

{f[1], 2+1^2}, {1^2, 1}, 2+1, 3}
share|improve this answer
3  
Block is not to blame for the symbol renaming but the outermost SetDelayed realising that your k is being injected in the innermost SetDelayed –  Rojo Jul 19 '13 at 5:01
    
@Rojo thanks, you are right. My answer is not correct in the explanation. I have to edit it and adjust. Indeed, doing some further tests I can confirm that the nesting of SetDelayed seems to be the cause of the renaming of var to var$. Honestly I still have to fully understand why, so at a glance I thought it was just Block. –  bobknight Jul 19 '13 at 8:37
    
@Rojo please let me know if I have to delete/edit/add my answer. I'm new on SE. I have seen there is a question with similar issue described: "If you look deep in the examples in the reference page for Module, under the section labeled Possible Issues, there's a little note that says "Variables are renamed in nested scopes"". –  bobknight Jul 19 '13 at 9:10
    
Sure, when you see a way to improve or correct your answer its better if you edit it. Welcome to SE :) –  Rojo Jul 19 '13 at 17:10
    
To correct this, simply note that it is Function and not Block that is using the dollar sign to support a lexical scoping-like behavior. –  Daniel Lichtblau Jul 19 '13 at 20:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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