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?
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
).
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$
Commented
Apr 3, 2015 at 15:25
Composition
it gets the point of what it does across.
$\endgroup$
Commented
Apr 3, 2015 at 15:30
@*
creates a function (which is not what @
does)?
$\endgroup$
... 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}
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:
h = f @ g; h[x]
andh = f @* g; h[x]
. $\endgroup$