11
$\begingroup$

This is a rather general question, which I fail to answer myself. I guess it is mainly due to my insufficient knowledge of the precise terms.

If I understand correctly, the following are equivalent:

f = Function[u, 3 + u]
f = Function[3 + #]
f = (3+#) &
f[x_]:=3+x

In all cases f[a] would yield 3+a. Similarly, f[a] is equivalent to f@@{a}.

I have mainly two questions:

  1. What is the right term to call the shorter version, i.e. the version where one uses @@, #, & etc.?
  2. When should I prefer the one method and not the other? It seems like many answers given around MA.SE uses the "shorter version". What are the advantages and disadvantages...

Bonus question: Note my first question. I hope I could get more fishing rods and less fish. In other words, what is the official term for these two notions? Where are can I find documentation of these differences? The examples I presented in the this questions are merely examples, and I try to understand where can I rigorously study these notions and similar ones.

$\endgroup$
4
  • 2
    $\begingroup$ Your questions are answered there Functions vs patterns and there f(a)vs.f@a $\endgroup$
    – Kuba
    Oct 10, 2013 at 13:28
  • 1
    $\begingroup$ @m_goldberg You probably meant to say that the first 3 produce OwnValues. But I think, this observation actually does not clarify matters - the fact that the function in the first 3 cases is stored in a variable is of secondary significance, since Function-s can be also used directly without being stored anywhere. $\endgroup$ Oct 10, 2013 at 13:32
  • 1
    $\begingroup$ 'Apply' (@@) is often just used when it is convenient. For example if you first generate a list using Table and then want the elements of that list to be arguments of your function. Like in f@@Table[i,{i,3}]. Also sometimes Apply is used to circumvent attributes like HoldAll. For example you can write Hold@@{1+2}, which evaluates to Hold[3], which is not the same as Hold[1+2] which just evaluates to itself. Some part of your question seems to be about notation, as two lines of code you suggest have the same FullForm. Ah there is too much to this question I can't make a point :P $\endgroup$ Oct 10, 2013 at 13:34
  • 3
    $\begingroup$ To the closers: this question is not exact dupe, because the answers linked do not fully explain the difference between long and short forms - which is not only in precedence. $\endgroup$ Oct 10, 2013 at 13:34

4 Answers 4

21
$\begingroup$

The brief forms /@, and @@@ are not exactly equivalent to the full forms of these operations, and also f[x] is not exactly equivalent to either of f[#]&[x] or f @@ {x}.

I will mention two aspects of the problem, but there likely are more (of course, in addition to the precedence - related aspect, already extensively described in the linked past discussions).

Evaluation

Consider the following example:

Hold[Print[1]]

which evaluates trivially to itself. However, the other forms you mentioned:

Hold @@ {Print[1]}

or

Hold[#] & [Print[1]]

will lead to evaluation leaks (Print will be evaluated).

One can probably come up with some contrived examples of other differences of a similar kind, but generally it is enough to say that these forms define different evaluation routes, so with enough effort, we can generate all kinds of differences. It is another matter that for most practical cases, such differences either are not there or don't matter.

Heads option

The main point here is that the brief forms like f @@@ expr and f @@ expr are parsed as Apply[f,expr,{1}] and Apply[f,expr], respectively, and do not allow one to explicitly pass the Heads option. Therefore, they will always use the global value for this option. And, should anyone change that option globally, there may return different results (from what one would normally expect) - just as the equivalent literal forms I mentioned above do.

You can do the following experiment (make sure you don't have any unsaved work):

SetOptions[Apply, Heads -> True] 

Then (taking this example from the help page for Apply):

f @@@ p[x][q[y]]

(* f[y][f[y]] *)

but the explicit literal form allows to pass the option explicitly:

Apply[f, p[x][q[y]], {1}, Heads -> False]

(* p[x][f[y]] *)

A similar situation is with Map and @@. I have described this in more detail here. Basically, you can't specify the Heads option when you use the short forms.

Note that resetting Heads option globally, as I did here, is strongly discouraged and can lead to disastrous consequences.

SetOptions[Apply, Heads -> False] 
$\endgroup$
12
  • 5
    $\begingroup$ I thought it would be interesting to note that I forgot to actually reset the Heads option in my workspace back to False, and was punished by a debugging nightmare which lasted for a good hour. I was lucky enough that the Apply on level one was, in this case, in my own code :) So, the lesson once again is that (re)setting options globally is bad, and particularly so for functions as fundamental as Map and Apply. $\endgroup$ Oct 10, 2013 at 16:27
  • $\begingroup$ Leonid, you sure do hang onto your kernel sessions, then :-) $\endgroup$
    – Yves Klett
    Oct 10, 2013 at 19:24
  • $\begingroup$ Leonid, I just read the last paragraph from the link to your book you provided above and now I'm wondering: Is that the convention you use when you write packages, i.e., not using shorthand notation and explicitly specifying Heads -> False? $\endgroup$
    – sebhofer
    Oct 10, 2013 at 20:58
  • 1
    $\begingroup$ @sebhofer Alas, I have to confess that I don't. The right thing to do perhaps would be to define your own aliases for Map and Apply which explicitly pass the option, and use them, but I usually am too careless. I am sure that resetting this option globally may / will cause severe problems, because I am sure that a lot of internal code also did not pass these options explicitly. That said, explicitly specifying Heads -> False is a right thing to do if you want you code really bulletproof (but surely not the only such thing). $\endgroup$ Oct 11, 2013 at 8:30
  • $\begingroup$ Leonid, you make some excellent points and I hope that will prevent many people from falling into these traps. However, I am a bit confused. First of all, SetOptions[Apply, Heads -> True];f @@@ {{1, 2}, {3, 4}, {5, 6}} gives me {f[1, 2], f[3, 4], f[5, 6]}, and not f[5, 6][f[1, 2], f[3, 4], f[5, 6]]. The latter also doesn't make much sense to me, as f[5,6] seems like a weird new Head. Furthermore I dislike the sentence: "The brief forms ... are not exactly equivalent to the full forms of these operations". After reading this, I thought your point would be that setting the option (...cont) $\endgroup$ Oct 11, 2013 at 11:57
9
$\begingroup$

If you do a performance test (say, using a million random numbers), you'll find that f = (3+#) & is the fastest. f[x_]:=3+x is significantly slower.

One way to think of @@ (i. e. Apply) is as "replace Head". Because that's exactly what it does. It removes the Head and puts whatever other Head you have provided. Very practical, but not always run-time efficient. Just compare Plus @@ somelist with Total, or even Tr @ somelist.

Also, if you look at Apply in http://reference.wolfram.com/legacy/flash/ you can see quite visually that Apply means "replace Head".

$\endgroup$
3
  • $\begingroup$ +1. Good point about efficiency. It is due to auto -compilation inside Map, to which the function defined by the rule is not amenable. $\endgroup$ Oct 10, 2013 at 19:42
  • $\begingroup$ +1 great animation of Mathematica functions! Never knew there is such a thing before. $\endgroup$
    – Leo Fang
    Oct 10, 2013 at 21:52
  • 1
    $\begingroup$ @LeoFang mathematica.stackexchange.com/q/27651/5478 $\endgroup$
    – Kuba
    Oct 11, 2013 at 7:22
5
$\begingroup$

These are all functionally equivalent forms of a Pure Function, sometimes called an anonymous function.

body[#] &

I use the operator form body[#]& when there is only one argument, but you can define a more complicated body using #[[2]] (Part) and #2 (Slot) used with List and Sequence arguments respectively.

Function[body[#]]

The full form Function[body[#]] is useful when you are having problems with precedence including other functions into your body. Compare

f@g[#] &@3 // Trace
f@Function[g[#]]@3 // Trace

Usually I use Pure Functions to apply several operations sequentially. I might even string together Built-In functions, user defined functions, and Pure Functions in a one-liner. But if I need to compute several side-calculations using different parts of several input variables, and then combine their results, I might go for

Function[vars, body[vars]]

where body includes a 'Module'. The only time I would do that is if I needed a complex operation which I only need once. Otherwise I would just make a user defined function through setting its DownValues

f[vars_]:=body[vars]

Whether I use Apply vs Prefix depends on whether I have a single List of arguments or several arguments in a Sequence.

f@Sequence[a, b] == f[a, b]
f @@ List[a, b] == f[a, b]
f@List[a, b] == f[{a, b}]
$\endgroup$
6
  • $\begingroup$ I prefer Composition for a sequence of operations, but this is ofc subjective. $\endgroup$
    – Kuba
    Oct 11, 2013 at 7:21
  • $\begingroup$ How does Composition work? Does it execute each function in turn, or does it compose a full form function, with all the command arguments properly nested, and apply that? $\endgroup$ Oct 11, 2013 at 12:25
  • $\begingroup$ There is only the last result. If you want to get them all you can use something like FoldList[#2 @ # &, var, {functionlist}] $\endgroup$
    – Kuba
    Oct 11, 2013 at 12:33
  • $\begingroup$ I think you missed my question. Suppose that you have something like Composition[f,Apply[g,#]&,h][x]. Would h[x] get executed? Let's find out. With h[x_] := CompoundExpression[CellPrint[x], yes[x]] we try Composition[f,Apply[g,#]&,h][x] and see that h[x] does get executed, so Composition applies each function in turn rather than composing first and applying the result. $\endgroup$ Oct 11, 2013 at 13:28
  • $\begingroup$ Ah, I wasn't sure what you are asking. That's good point, I think it is first composing and them applying. However I'm not sure if it changes anythig (I've failed to produce different results). $\endgroup$
    – Kuba
    Oct 11, 2013 at 13:39
2
$\begingroup$

In answer to your first question, you can refer to the various special forms of input depending on where and how it is used in the expression. Mathematics and Mathematica both use forms such as prefix, infix and postfix form. You can read more here: Special ways to Input Expressions

For completeness, I'll show several obvious examples:

Prefix form

  • f(x): Here f is the prefix operator

Infix form

  • a + b: Here + is the infix operator because it sits between its arguments

Postfix form

  • 5!: Here ! comes after the 5 on which it is operating.

It is probably worth mentioning that, regardless of the input form used, Mathematica translates all input into a standard prefix form: Head[argument1, argument2, ...]

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.