17
$\begingroup$

I'm a big fan of Mathematica's shorthand notation, things like @ and /@, which I use the most. It's really useful when I'm quickly whipping something up.

However, something has always driven me a bit nuts. If I want to first map a function to each element in a list, and then apply another function to the whole list, like this:

In[338]:= a = {2, 8, 5};
SecondFn@FirstFn /@ a

Out[339]= {SecondFn[FirstFn][2], SecondFn[FirstFn][8], 
 SecondFn[FirstFn][5]}

You can see that it's first applying SecondFn to FirstFn, and then mapping that combination of functions to each element. I get that by default @ apparently takes precedent in the order of operations over /@, but is there an easy way to make it still go from "right to left" without using parentheses?

For example, I know I can do this to get the result I want:

In[340]:= a = {2, 8, 5};
SecondFn@(FirstFn /@ a)

Out[341]= SecondFn[{FirstFn[2], FirstFn[8], FirstFn[5]}]

But at that point I have to put a pair of parentheses, at which point I might as well just use brackets like normal (in fact it contains the extra symbol @).

Is there a way to do this? thanks!

$\endgroup$

4 Answers 4

18
$\begingroup$

You could use the operator form of Map instead:

SecondFn @ Map[FirstFn] @ {2, 3, 5}

SecondFn[{FirstFn[2], FirstFn[3], FirstFn[5]}]

or

comp = SecondFn @* Map[FirstFn];
comp @ {2, 3, 5}

SecondFn[{FirstFn[2], FirstFn[3], FirstFn[5]}]

$\endgroup$
2
  • 1
    $\begingroup$ Nice, that application of the operator form of Map! (Your second solution can also be written in one line as SecondFn @* Map[FirstFn] @ {2, 3, 5}.) $\endgroup$ Aug 22, 2017 at 14:47
  • $\begingroup$ Thank you, this first one is exactly what I'm going for here. "right to left" and no enclosing brackets/parens. $\endgroup$ Aug 22, 2017 at 14:54
13
$\begingroup$
FirstFn /@ a // SecondFn
SecondFn[{FirstFn[2], FirstFn[8], FirstFn[5]}]
$\endgroup$
1
  • $\begingroup$ Hi, thanks for the response, and this is nice but still has a downside for me: it's not going "right to left". It seems like if I strung together a bunch of maps and functions I'd be bouncing around between left and right. $\endgroup$ Aug 22, 2017 at 14:53
5
$\begingroup$

A solution using only prefix notation is

List /* f @@ g /@ {x,y,z}
(* Out: f[{g[x],g[y],g[z]}] *)

Edit. A slightly nicer version (cf the order of the functions) uses Composition (@*) instead of the above RightComposition (/*):

f @* List @@ g /@ {x,y,z}
(* Out: f[{g[x],g[y],g[z]}] *)

This is still less elegant than the (rightfully) accepted answer, but it has the benefit of allowing one to use any function rather than just List.

$\endgroup$
4
$\begingroup$
f2 @ Function[, f1 @ #, Listable] @ {1, 2, 3}

f2[{f1[1], f1[2], f1[3]}]

We can also use SetAttributes

SetAttributes[a, Listable]
a[x_] := b @ x

c @ a @ {1, 2, 3}

c[{b[1], b[2], b[3]}]

$\endgroup$
2
  • $\begingroup$ Why/how does this work? I can see that it does, even though Mma "complains" about the empty first argument of Function, and the missing & in combination with the #, by highlighting the first comma and the # in pink in my input. $\endgroup$ Aug 22, 2017 at 16:21
  • 1
    $\begingroup$ If the highlighting disturbes you try f2@Function[Null, f1@Slot@1, Listable]@{1, 2, 3} $\endgroup$
    – eldo
    Aug 22, 2017 at 16:25

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.