7
$\begingroup$

This question already has an answer here:

What's the difference between setting a function's attribute as Listable and using Map? I understand that Map is more specific, the question is rather about action on single depth lists.

$\endgroup$

marked as duplicate by Leonid Shifrin, MarcoB, RunnyKine, m_goldberg, user9660 Apr 27 '16 at 4:22

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

9
$\begingroup$

The main difference can been seen when dealing with list of lists. Consider the following list:

lis = {{1, 2, 3}, {3, 4, 5}, {5, 6, 7}};

Lets create a Listable function g

SetAttributes[g, Listable]

Now we Map a non-listable function f and apply the listable function g

Map[f, lis]

(* {f[{1, 2, 3}], f[{3, 4, 5}], f[{5, 6, 7}]} *)

g[lis]

(* {{g[1], g[2], g[3]}, {g[3], g[4], g[5]}, {g[5], g[6], g[7]}} *)

Clearly the Listable function g, continues until it's applied down to a non-list expression. Whereas Map by default applies to Level 1. One can get the same behavior with Map by using the 3rd argument (level specification):

Map[f, lis, {2}]

(* {{f[1], f[2], f[3]}, {f[3], f[4], f[5]}, {f[5], f[6], f[7]}} *)

On Single-depth lists, they both behave the same:

lis2 = {1, 2, 3, 4, 5, 6};

Map[f, lis2]
g[lis2]

(*
   {f[1], f[2], f[3], f[4], f[5], f[6]}
   {g[1], g[2], g[3], g[4], g[5], g[6]} 
*)

Performance does not seem to vary much either. Consider the following functions:

SetAttributes[k, Listable];
k[x_]:= x^2 + 2x
u[x_]:= x^2 + 2x

Let's apply them to a large list:

lis3 = RandomReal[2, 10^6];
k[lis3]; // RepeatedTiming
Map[u, lis3]; // RepeatedTiming

(* {1.26, Null}    
   {1.242, Null} *)

Of course, if you are going to use Map, you're better off using a pure function since that increases performance by a lot:

Map[#^2 + 2 # &, lis3]; // RepeatedTiming

{0.065, Null}

To be fair, I should also mention that you can make a Listable pure function (see comments) that performs about the same as Map with a pure function. As Szabolcs mentioned in the comments here is an example where the Listable version appears to have no Map counterpart:

g[{1, {2, 3}, 4, h[x]}]

(* {g[1], {g[2], g[3]}, g[4], g[h[x]]} *)

So at least, that's a difference. And I'm sure one can come up with many such examples.

$\endgroup$
  • $\begingroup$ If you define k and u as #^2 + 2 # &, set k to be Listable, and then do k[lis3] vs u /@ lis3, my machine says that the former is even faster. $\endgroup$ – march Apr 26 '16 at 19:55
  • $\begingroup$ @march. On mine it's slower, but I should probably mention that option too to be fair. $\endgroup$ – RunnyKine Apr 26 '16 at 20:00
  • $\begingroup$ g[{1, {2, 3}, 4, f[x]}] is a good example to include too. This cannot be done with Map at all, not even by mapping at level -1. $\endgroup$ – Szabolcs Apr 26 '16 at 20:48
  • $\begingroup$ @Szabolcs it comes close, oh so close. {f[1], {f[2], f[3]}, f[4], h[f[x]]} $\endgroup$ – rcollyer Apr 26 '16 at 21:08
  • $\begingroup$ @Szabolcs. Thanks, I included your example. $\endgroup$ – RunnyKine Apr 26 '16 at 21:22

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