30
$\begingroup$

What is the difference between

f@*g@*h@x

and

f@g@h@x

Both evaluate to

f[g[h[x]]]

If they're the same, why introduce Composition as a new feature?

$\endgroup$
  • $\begingroup$ Related: (54762) $\endgroup$ – Mr.Wizard Apr 4 '15 at 0:04
  • 3
    $\begingroup$ Observe the difference between h = f @ g; h[x] and h = f @* g; h[x]. $\endgroup$ – David Zhang Apr 4 '15 at 15:42
34
$\begingroup$

Clearly the @ notation is inspired by the usual mathematical notation for function composition. f@g[x] looks very similar to the mathematical notation $(f\circ g)(x)$. But it is important to understand that @ does not denote function composition. In mathematical notation $f\circ g$ is also a function. In Mathematica f@x is simply a different way to write f[x], but f@g is not (generally) a function. Both f@x and f[x] parse to the exact same Mathematica expression.

So what is the true equivalent of $f \circ g$? It is Composition[f, g] which can be more concisely written as f @* g since version 10, and can be used in situations where we need a function without applying it to an argument (e.g. with Map, or as an operator with Dataset).


Both of your examples evaluate to the very same things in the end, so they behave equivalently in this case. But the way Mathematica arrives to the same end result is different:

f@g@h@x parses to an expression with the FullForm f[g[h[x]]], which doesn't evaluate further. There's no evaluation step.

f@*g@*h@x parses to an expression with the full form Composition[f,g,h][x], which then evaluates to f[g[h[x]]].


It's also worth pointing out that @ and @* have different precedences and associativity properties as operators. f@g@x is equivalent to f@(g@x) and f@*g@x is equivalent to (f@*g)@x. Writing ...[...] has a different precedence again so f@*g[x] is the same as f@*(g[x]) (i.e. it's not the same as f@*g@x).

$\endgroup$
  • $\begingroup$ Could you say a bit more about the different meanings? $\endgroup$ – orome Apr 3 '15 at 15:24
  • 2
    $\begingroup$ Just to make it more clear, the big difference is that f @ g is the same as f[g], while f @* g is roughly equivalent to f[g[#]] &. For example of usage, StringLength @* ToString /@ Range[10] works whereas StringLength @ ToString /@ Range[10] does not. $\endgroup$ – 2012rcampion Apr 3 '15 at 15:25
  • 1
    $\begingroup$ That's why I added "roughly equivalent." and changed the first "equivalent" to "is the same," to make clear the differences. But if you don't know the details about Composition it gets the point of what it does across. $\endgroup$ – 2012rcampion Apr 3 '15 at 15:30
  • 1
    $\begingroup$ @Szabolcs: So is it fair to say that the (or at least a) key conceptual distinction is that @* creates a function (which is not what @ does)? $\endgroup$ – orome Apr 3 '15 at 17:14
  • 2
    $\begingroup$ @raxacoricofallapatorius Yes. That is correct. $\endgroup$ – Szabolcs Apr 3 '15 at 17:14
19
$\begingroup$

... why introduce Composition as a new feature?

Composition is used to create a new anonymous function that can be used in all the standard ways such as Map and Apply etc. To achieve the same thing without it one needs a Function. Much like operator forms the use of Composition allows one to eliminate extraneous Function constructs which can make code more linear and easier to read. The short form @* and its companion /* (see RightComposition) make its application pleasingly concise.

Composition is not typically used for a single application but instead when one wishes to perform an operation multiple times. Here are some related form:

f@*g@*h /@ {x, y, z}
f@g@h@# & /@ {x, y, z}
f /@ g /@ h /@ {x, y, z}

Each of these evaluate the same way in this particular case but there are differences that are not immediately apparent. We can see some of them if we define:

f = HoldForm; g = Print; h = Sqrt;

Now:

f@*g@*h /@ {x, y, z}
f@g@h@# & /@ {x, y, z}
f /@ g /@ h /@ {x, y, z}

enter image description here

Because Composition does not hold its arguments the Symbols g and h are resolved to Print and Sqrt in the output from the first line. In the second line f resolves first to HoldForm and as a result g and h remain verbatim. Finally in the last line each function application is evaluated sequentially therefore the Print fires and Null is returned as the actual output.

See also:

$\endgroup$
  • 1
    $\begingroup$ Done. +1 for the trouble, and for the quality answer. $\endgroup$ – Daniel W Apr 9 '15 at 15:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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