Why is Unevaluated[#]& different from Unevaluated?

{a, b, c} = {1, 2, 3};
Unevaluated /@ Unevaluated@{a, b, c}
(* {Unevaluated[a], Unevaluated[b], Unevaluated[c]} *)
Unevaluated[#]& /@ Unevaluated@{a, b, c}
(* {Unevaluated[1], Unevaluated[2], Unevaluated[3]} *)


Why are the outputs different? What is the difference between using Unevaluated and Unevaluated[#]&? I thought that for any function f we could use "f" interchangeably with "f[#]&". Is there a special interaction between Unevaluated and Map?

• Related Commented Jan 8, 2018 at 19:25

The two are not equivalent. Even iff lacks special attributes.

Assuming no special attributes are present, a function's arguments are always evaluated before the function is called. This event occurs twice with f[#] &[x], but only once with f[x]. Now, if everything has been fully evaluated, then you won't see a difference, but if something is marked as "do not evaluate", then you can see a difference.

(This can be very counter-intuitive if you're only used to traditional programming languages.)

Here's a counterexample:

Print     [Unevaluated[2 + 2]]      (* prints 2 + 2 *)
Print[#] &[Unevaluated[2 + 2]]      (* prints 4     *)


However, I think (though I'm not 100% sure I've considered all the cases) that the following two would be equivalent if f lacks special attributes:

f
f[Unevaluated[#]] &

• OK, so you've showed there exists an extra step. But what exactly is this step? Commented Jan 9, 2018 at 13:42
• @Ruslan: I'm not sure how to point to it and say "there it is", but if you understand that Unevaluated only suppresses 1 step of evaluation whereas Hold suppresses all steps, then you can see that invoking an extra function with an expression will add an extra evaluation step for the expression. It's simply a consequence of a function's arguments getting evaluated before the function is called. That happens twice in the second example but once in the first (because there are two function calls in the second but one in the first). Commented Jan 9, 2018 at 14:31
• Ah, I didn't understand the difference between Unevaluated and Hold. Commented Jan 9, 2018 at 14:36
• @Ruslan: Yeah, you're probably not the only one. I had to get my hands dirty and write a whole simulator in Mathematica before really understanding this stuff in the language. It's definitely not easy to get what's really going on if you only use it casually. Commented Jan 9, 2018 at 14:45
• @Szabolcs: I didn't mean "not listing every difference" is what made it wrong, I meant literally the first sentence ("That is only true if the function has no special attributes.") is simply false. (And yes, pedantically it's true in the mathematical sense of "only if", but false for the normal English sense.) The part about discarding extra arguments is indeed true but doesn't really seem relevant given the question was about a single argument, unless I'm missing something/misunderstanding it. (?) Commented Jan 9, 2018 at 15:46

I thought that for any function f we could use "f" interchangeably with "f[#]&".

That is only true if the function has no special attributes. Function effectively removes those attributes, and all other special behaviour.

For example,

Hold[1 + 1]
(* Hold[1 + 1] *)

Hold[#] &[1 + 1]
(* Hold[2] *)

Function[x, Hold[x], HoldAll][1 + 1]
(* Hold[1 + 1] *)


(For the last one, see the 3rd argument of Function.)

• Thanks Szabolcs, even though this is not the right answer in the context of Unevaluated, it is still useful to know in other contexts. Commented Jan 10, 2018 at 15:07

The head Unevaluated is a symbol with the HoldAllComplete attribute. The head Unevaluated[#]& is not a symbol and thus has no attributes to suppress Mathematica's evaluation of its tail.