# With/Function(/etc) replacement behaviour

Can anyone explain to me this behaviour? I've been having more than a couple of similar doubts these last weeks.

For example

f[_?NumericQ] := 8;


Now, if I do

With[{a = f[a]}, HoldForm@Block[{NumericQ = True &}, a]]


I get

Block[{NumericQ = True &}, f[a]]


And if I do

Block[{NumericQ = True &}, f[a]]


I get

8


So far so good... Another so-far-so-goodie is (notice the :=)

With[{a := f[a]}, Block[{NumericQ = True &}, a]]

8


Question: Can anyone help me understand why this output?

With[{a = f[a]}, Block[{NumericQ = True &}, a]]

f[a]


Could it be that With (= version) not only evaluates and replaces, but also guarantees that the replaced expression won't be reevaluated no matter what until the With is exited? If that's the case I wasn't expecting that. What's happening here?

EDIT

Question also applies to Function

Block[{NumericQ = True &}, #] &[f[a]]

f[a]


And not just those too. Everything I try behaves the same way... A couple of other examples

Block @@ (Hold[{NumericQ = True &}, exp] /. exp -> f[a])

With[{a := Evaluate@f[a]}, Block[{NumericQ = True &}, a]]


both give f[a]

EDIT

With[{g = h}, h = 8; Print[g] ]


prints 8, not h, so clearly h is reevaluated inside the With in this case, so g is not so constant.

EDIT

Ok, another couple of examples

In:= ClearAll[h, f];
h := 8 /; NumericQ["a"];
f[_?NumericQ] := 8;


Now, both h and f[a] remain unevaluated

In:= {h, f[a]}

Out= {h, f[a]}


Now, with the OwnValues everything works as expected

In:= With[{g = h},
Block[{NumericQ = True &}, g]]

Out= 8


But with the DownValues, it doesn't

In:= With[{g = f[a]},
Block[{NumericQ = True &}, g]]

Out= f[a]


Similarly

f[a_?NumericQ] := 8;
g[e_] := Block[{NumericQ = True &}, e]


f[a] evaluates to f[a], but weirdly

In:= g[Unevaluated@f[a]]

Out= 8

In:= g[f[a]]

Out= f[a]


f[_?NumericQ] := 8

With[{a = f[a]}, Block[{NumericQ = True &}, a]]


outputs f[a].

This is because of caching of the result of Conditions and PatternTests. Compare with this:

With[{a = f[a]}, Block[{NumericQ = True &}, Update[]; a]]

(* ==> 8 *)


Generally, making global changes that might affect the outcome of a Condition will have unpredictable results due to caching---unless you use Update[] after each change.

• Szabolcs to the rescue......
– Rojo
Feb 15, 2012 at 8:30
• Interesting, the relation of this behavior to caching wasn't obvious to me. +1. Feb 15, 2012 at 13:13
• @Leonid and Rojo: the clue was that TracePrint didn't show NumericQ being evaluated for the second time. Feb 15, 2012 at 13:15
• @Szabolcs Yes, I also used Trace and saw that there was no second evaluation. I just read your answer first, and realized that without Trace, this wouldn't be something I'd guess right away. Feb 15, 2012 at 13:17

See the answers to this question.

The short answer is that, yes, With is designed for creating local constants, so once the local expressions are initialised, they won't be re-evaluated.

Using the {a := f[a]} notation gets around this design feature of With. To be honest, though, I have never seen it used before. It is not mentioned in the documentation, and I can't help thinking that it breaks something in subtle ways.

Of course Block[{a = f[a], NumericQ = True &}, a] gives a $RecursionLimit error, but returns 8. Is there a reason why Block[{NumericQ = True &}, f[a]] doesn't fulfil your purpose? In response to your edit, Block[{NumericQ = True &}, #] & [f[a]] doesn't give your desired output because the f[a] is outside the Block scoping construct. Again, see Leonid's answer to the previously mentioned question as well as the other answers there. • I wanted f[a] evaluated with normal definitions (NumericQ meaning what it means) and afterwards (if necessary) reevaluated letting it match the ?NumericQ definition. I thought I would get that behaviour with the With or with a Function but I was clearly wrong – Rojo Feb 15, 2012 at 5:44 • With may be designed to define constants that cannot be changed, but I definately expected Function to simply replace it's arguments and evaluate. Shouldn't f[a] be put inside the Block before the Block is even considered? – Rojo Feb 15, 2012 at 5:53 • I think I've seen SetDelayed used in With discussed on SO. Maybe by Simon or Leonid. Feb 15, 2012 at 6:15 • @Mike I learned this syntax from Szabolcs, relatively recently. Feb 15, 2012 at 13:10 You can use TracePrint to try to understand how evolves the evaluation step by step: In:= TracePrint[With[{b=f[a]},Block[{NumericQ=True&},b]]] During evaluation of In:= With[{b=f[a]},Block[{NumericQ=True&},b]] During evaluation of In:= With During evaluation of In:= f[a] During evaluation of In:= f During evaluation of In:= a During evaluation of In:= NumericQ[a] During evaluation of In:= NumericQ During evaluation of In:= a During evaluation of In:= False During evaluation of In:= Block[{NumericQ=True&},f[a]] During evaluation of In:= Block During evaluation of In:= True& During evaluation of In:= Function During evaluation of In:= NumericQ=Unevaluated[True&] During evaluation of In:= Set During evaluation of In:= NumericQ=True& During evaluation of In:= True& During evaluation of In:= f[a] During evaluation of In:= f[a] Out= f[a]  As Verbeia said before, you can see that NumericQ[a] is evaluated before it goes to the Block. In the other hand, if you use the delayed set: In:= TracePrint[With[{b:=f[a]},Block[{NumericQ=True&},b]]] During evaluation of In:= With[{b:=f[a]},Block[{NumericQ=True&},b]] During evaluation of In:= With During evaluation of In:= Block[{NumericQ=True&},f[a]] During evaluation of In:= Block During evaluation of In:= True& During evaluation of In:= Function During evaluation of In:= NumericQ=Unevaluated[True&] During evaluation of In:= Set During evaluation of In:= NumericQ=True& During evaluation of In:= True& During evaluation of In:= f[a] During evaluation of In:= f During evaluation of In:= a During evaluation of In:= NumericQ[a] During evaluation of In:= NumericQ During evaluation of In:= True& During evaluation of In:= a During evaluation of In:= (True&)[a] During evaluation of In:= True During evaluation of In:= 8 During evaluation of In:= 8 Out= 8  Evaluation of f[a] happens inside the Block. I changed the With variable to b, so you can see the difference, but the output is the same using a as variable, I don't get any $RecursionLimit error (using Mathematica 8).

• I know it evaluates before the Block but how can I make it evaluate again inside the Block?
– Rojo
Feb 15, 2012 at 6:02
• Well, it seems the right answer is with the delayed set, or with Hold, something like: With[{b = Hold[f[a]]}, Block[{NumericQ = True &}, ReleaseHold[b]]]
– FJRA
Feb 15, 2012 at 6:08
• my bad, I wasn't clear. I want it to be evaluated both outside the block with NumericQ meaning it's regular meaning, and then again inside the Block with the redefined NumericQ. Your code works but it only evaluates f[a] inside the Block
– Rojo
Feb 15, 2012 at 6:10