1
$\begingroup$

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?

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

1 Answer 1

1
$\begingroup$

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}
$\endgroup$
5
  • 3
    $\begingroup$ Block is not to blame for the symbol renaming but the outermost SetDelayed realising that your k is being injected in the innermost SetDelayed $\endgroup$
    – Rojo
    Jul 19, 2013 at 5:01
  • $\begingroup$ @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. $\endgroup$
    – bobknight
    Jul 19, 2013 at 8:37
  • $\begingroup$ @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"". $\endgroup$
    – bobknight
    Jul 19, 2013 at 9:10
  • $\begingroup$ Sure, when you see a way to improve or correct your answer its better if you edit it. Welcome to SE :) $\endgroup$
    – Rojo
    Jul 19, 2013 at 17:10
  • $\begingroup$ 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. $\endgroup$ Jul 19, 2013 at 20:11

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.