# Does function call via @ ignore HoldFirst attribute?

I was trying to test whether using func[x,y] is the same as func[#,y]&@x:

SetAttributes[test, HoldFirst]
test[1 + 2 - 3, 5 - 5]
test[#, 5 - 5] &@(1 + 2 - 3)


test[1 + 2 - 3, 0]

test[0, 0]

So apparently, HoldFirst is ignored in the second case. Why is it so? Is the argument of @ evaluated before actually being passed?

• (1 + 2 - 3) is evaluated before being passed. You can try test[#, 5 - 5] &@Defer[(1 + 2 - 3)] to prevent evaluation of (1 + 2 - 3). – kglr Nov 11 '16 at 7:44
• @kglr This isn't correct. There are many misunderstanding about Defer. The most important thing to remember is that it deal with formatting and not evaluation. It is only useful in a notebook and only if you mean to copy the output or edit it otherwise in a notebook. In a way it is for user interaction. It is not useful for programming and expression manipulation and has no effect when running the kernel without a front end. You example is effectively the same as test[#, 5 - 5] &@HoldForm[(1 + 2 - 3)]. The head HoldForm or Defer stays there it just doesn't print. – Szabolcs Nov 11 '16 at 12:47
• BTW the same applies to Interpretation. It's all about formatting and user interaction within a notebook and has nothing to do with expression manipulation or programming, nor does it have any effect when there is no notebook environment. – Szabolcs Nov 11 '16 at 12:48
• @Szabolcs excellent point; thank you. – kglr Nov 11 '16 at 13:52
• I think you might find the answers to an old question of mine useful: stackoverflow.com/q/5686494 – Mr.Wizard Nov 12 '16 at 8:33

andre has given a good answer. I will add a little further clarification. The function f[#]& is a different function than the function f and does not have its attributes. It is the short form of

Function[x, f[x]]


Assume

Clear[f]; SetAttributes[f, HoldFirst]


has been evaluated. Even though f is HoldFirst, both

Function[x, f[x]][1 + 1]


and

Function[x, f[x]] @ (1 + 1)


give

f[2]

When the pure function is also given the attribute HoldFirst, evaluation goes as you expect.

Function[x, f[x], HoldFirst] @ (1 + 1)


f[1 + 1]

This is intended, but is one of the main premature evaluation case when one works with unevaluated expression.

Particularly f @ expression is not equivalent to f[#]& @ expression See :

SetAttributes[f, HoldFirst]
f[1 + 1]
f[#]& @ (1 + 1)


f[1 + 1]
f[2]

but :

f @ (1 + 1)


f[1 + 1]

The @ is not responsible of the premature evaluation. The cause is rather the use of #& applied to an expression.

Edit

To confirm this, one can try :

f[#]& [1 + 1]


f[2]

There are two separate issues here, which you are confusing.

Does function call via @ ignore HoldFirst attribute?

No, it doesn't. f[x] and f@x are different textual representations of the very same expression. Writing it either way has absolutely no effect on evaluation. The parser converts both into the very same internal representation. The evaluator works with this internal representation and doesn't know how you wrote the code originally, as f[x] or f@x.

I was trying to test whether using func[x,y] is the same as func[#,y]&@x

This is an entirely different question, and has nothing to do with using the @ character. It's about using a pure function. Note that func[#,y]&@x and func[#,y]&[x] are exactly the same thing. The latter has no @ in it.

By default, any pure function behaves as if it had no attributes (such as HoldAll, etc.). Demo:

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


Let's write this using its FullForm:

Function[Hold[#]][1 + 1]


If you look up Function, you will see that we can construct a funtcion with the same behaviour using the following syntaxes too:

Function[x, Hold[x]]


or

Function[Null, Hold[#]]


If we write it this way, we get access to the third argument, where we can specify attributes. See the Function documentation page for more information.

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