Confused with HoldForm in Postfix notation

Why does the following code produce different result? In my mental model, they should be the same.

Table[With[{x = i^k}, HoldForm[x]], {k, 1, 5}]
With[{x = i^k}, HoldForm[x]] // Table[#, {k, 1, 5}] &


Output:

{i,i^2,i^3,i^4,i^5}
{i^k,i^k,i^k,i^k,i^k}


The difference is because in the second case

With[{x = i^k}, HoldForm[x]] // Table[#, {k, 1, 5}] &


The With expression is evaluated (giving HoldForm[i^k]) before it is substituted inside the placeholder in Table. To prevent thise pre-evaluation wrap it around Unevaluated as follows:

Unevaluated[With[{x = i^k}, HoldForm[x]]] // Table[#, {k, 1, 5}] &


Which gives as before:

{i, i^2, i^3, i^4, i^5}

• What is the difference between Unevaluated and HoldForm? They seem to be similar intuitively. Jan 16, 2014 at 7:53
• To see the difference try: Head[Unevaluated[f[x]]] vs Head[HoldForm[f[x]]] Jan 16, 2014 at 7:57
• @CodeMocker While Runny's workaround indeed solves your problem, it does not give an insight on why With is evaluated before Table in one case but not in the other. For an explanation, please see my answer. Jan 16, 2014 at 10:24

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 Prints 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

• I like when you explain things with those Prints. It's very useful method.
– Kuba
Jan 16, 2014 at 12:55
• @Kuba ...and a poor man's debugger :) Jan 16, 2014 at 13:00