To be more specific, the difference is not because of the postfix application but because of the pure function (the part with #
and &
) application:
Table[With[{x = i^k}, HoldForm[x]], {k, 1, 5}] (* no pure function *)
(* ==> {i, i^2, i^3, i^4, i^5} *)
With[{x = i^k}, HoldForm[x]] // (Table[#, {k, 1, 5}] &) (* postfix pure function *)
(* ==> {i^k, i^k, i^k, i^k, i^k} *)
(Table[#, {k, 1, 5}] &) @ With[{x = i^k}, HoldForm[x]] (* prefix pure function *)
(* ==> {i^k, i^k, i^k, i^k, i^k} *)
Accordingly, if you simplify your example, and put some Print
s in it:
Block[{k = 1}, Print[2]; With[{x = k}, Print[1]; HoldForm@x]]
During evaluation of In[17]:= 2
During evaluation of In[17]:= 1
(* ==> 1 *)
Block[{k = 1}, Print[2]; #] &@With[{x = k}, Print[1]; HoldForm@x]
During evaluation of In[17]:= 1
During evaluation of In[17]:= 2
(* ==> k *)
As you can see, in the last case, the With
is evaluated first, not Block
, resulting in thus a replacement x -> k
, so Block
cannot replace x
in the second step as there is no x
anymore in the expression.
An even more simple example that shows the reversed evaluation sequence for pure function application compared to normal, nested expression evaluation:
(Print[2]; Print[1];)
2
1
(Print[2]; #;) & @ Print[1]; (* or: Print[1]; // (Print[2]; #;) & *)
1
2