# How can I define a Listable function only apply to a vector?

Consider the function f which should behave as

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

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


The following code doesn't worked as expectation

fromDig[ls_?VectorQ] := 10^Range[Length@ls - 1, 0, -1].ls;
SetAttributes[fromDig, Listable];
fromDig@{{1, 2}, {3, 4}, {5, 6}}


I figured out a way, using Compile,

Clear["Global*"];
cfromDig = Compile[{{A, _Integer, 1}},
10^Range[Length@A - 1, 0, -1].A, RuntimeAttributes -> {Listable}];
cfromDig[{{1, 2}, {3, 4}, {5, 6}}]


Is there a better way?

• I am not sure if I understand, but why not just: fromDig2[ls_List] := 10^Range[Length@# - 1, 0, -1].# & /@ ls; fromDig2@{{1, 2}, {3, 4}, {5, 6}}? (or FromDigits /@ {{1, 2}, {3, 4}, {5, 6}}:) ) Sep 26, 2013 at 5:59
• ...or fromDig3[ls__] := 10^Range[Length@{ls} - 1, 0, -1].{ls}; fromDig3 @@@ {{1, 2}, {3, 4}, {5, 6}}
– gpap
Sep 27, 2013 at 10:47

I'm pretty sure this is a duplicate but I spent 15 minutes looking for it and couldn't find it, so I'm just going to answer for now.

Instead of using Listable you can manually map over non-vector lists:

f[v_?VectorQ] := oper[v]
f[ls_List] := f /@ ls;

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

{oper[{1, 2}], oper[{3, 4}], oper[{5, 6, 7}]}


### Extension

In an attempt to make this answer more unique, consider the advanced behavior of Listable functions wherein non-list arguments are distributed:

SetAttributes[ff, Listable]
ff["x", {1, 2, 3}, {4, 5, 6}]

{ff["x", 1, 4], ff["x", 2, 5], ff["x", 3, 6]}


We may wish to have this behavior extended, in a fashion at least, to our "vector atoms" as used above. The simplest method I can think of is to use Thread, which has the same behavior as Listable though only at level one, and guard the vectors form recognition and threading. Here an unoptimized first pass at implementation:

g[a___] /; MemberQ[{a}, x_List /; ! VectorQ[x]] :=
Module[{h},
g @@@ Replace[Thread@Replace[Hold[a], v_?VectorQ :> h[v], {1}], h@x_ :> x, {2}]
]


Now:

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

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


Note that the vector {2, 3} is distributed as 1 is, while the nested lists are threaded. When {4} is encountered it is also treated as atomic, but its surrounding List is transferred to the output: {g[1, {2, 3}, {4}]}`.

• I have the search problem for long time, too :)) Do you think we should move meta.mathematica.stackexchange.com/questions/1086/… question to the main site... Sep 26, 2013 at 8:34
• @s.s.o It's migrated now. I hope you get an answer at last. Sep 26, 2013 at 12:03