Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I would like to have a test that determines if a particular function is Listable. In the case of Symbols this is merely a matter of checking Attributes. Function definitions with the Listable attribute are a bit more involved but quite easy.

However I specifically want to test for inherent listability in as many cases as possible.

For example consider the function from Case #4 in Alternatives to procedural loops and iterating over lists in Mathematica:

(3 - #)/(7 * #) &

This function is inherently listable:

fn = (3 - #)/(7*#) &;
Map[fn, {1, 2, 3}]
fn @ {1, 2, 3}
{2/7, 1/14, 0}
{2/7, 1/14, 0}
  • One must consider Functions with multiple arguments, both the Slot and named parameter type.

  • Ideally the test would handle pattern-based (DownValues) functions to the extent that is possible.

share|improve this question
1  
What if your list is {3, 4, {1,2}}? Then, listable f, gives {f[3], f[4], {f[1], f[2]}}. So, while (3 - #)/(7 #)& is inherently listable, I don't think it is completely listable. So, ListableQ will have some limitations. –  rcollyer Sep 1 '13 at 14:34
1  
@rcollyer / is a listable binary operator so it works out fine since both arguments will have the same shape. –  ssch Sep 1 '13 at 15:25
    
@rcollyer I don't see the problem with your example. Perhaps you have another one? –  Mr.Wizard Sep 1 '13 at 22:38
    
@Mr.Wizard initially it was very clear to me when I wrote, not so much now, especially with ssch's comment. I need to see if I can recover what I intended, but my mental tape drive is faulty. :P –  rcollyer Sep 3 '13 at 12:45
    
@rcollyer I know that feeling. Too well. –  Mr.Wizard Sep 3 '13 at 13:25

2 Answers 2

This is what I have so far. It's far from complete, but still a good start I think.

listableQ[s_Symbol] /; MemberQ[Attributes @ s, Listable] := True
listableQ[s_Symbol] := MatchQ[DownValues[s], {__?test2}]

listableQ[Verbatim[Function][_, _, attr_]] /; ! FreeQ[{attr}, Listable] := True
listableQ[Verbatim[Function][vars_, body_, ___]] := test1[vars, body]
listableQ[body_ &] := 
  Cases[Unevaluated[body], _Slot, {0, -1}, Heads -> True] /. x_ :> test1[x, body]

SetAttributes[test1, HoldAll];
test1[vars_, body_] :=
  Cases[Unevaluated[body],
    h_[args___] /; ! FreeQ[Unevaluated[{args}], Alternatives @@@ HoldPattern[vars]] :> h,
    {0, -1}
  ] ~MatchQ~ {__?listableQ}

test2[lhs_ :> rhs_] :=
  Union @@ Cases[Unevaluated[lhs],
    Verbatim[Pattern][p_, _] :> Hold[p],
    {0, -1}, Heads -> True
  ] /. x_ :> test1[x, rhs]

Here is a very basic test; qq represents a generic function that isn't listable.

ff[a_, b__, c : _List] := a^2/Sign[b^2 + c] + qq[z]
f2[a_, b__, c : _List] := qq[a, b^2] + c

listableQ /@ {
  (3 - #)/(7*#) &,
  (3 - #)/(qq[7]*#) &,
  qq[(3 - #), (7*#)] &,
  Function[x, x + qq[5] + x/2],
  Function[x, qq[x + 5, x/2]],
  Function[, qq[(3 - #), (7*#)], Listable],
  ff,
  f2
 }

{True, True, False, True, False, True, True, False}

share|improve this answer
    
I am aware that there are ways that this fails, and moreover, that the question itself may be hard to answer in a complete way. For example, if qq[7] were to return {1, 2} this would break listability of second function. Nevertheless I am interested in exploring and improving this kind of test. –  Mr.Wizard Sep 1 '13 at 13:36
    
Additionally I realize that my ff and f2 functions are poorly conceived; they were hasty examples. I'll revisit this tomorrow. –  Mr.Wizard Sep 1 '13 at 14:02

The naive one-argument test:

naiveListableQ[f_] := f[{1, 2}] === f /@ {1, 2}

Cons:

  • Evaluates the function
  • Can give incorrect result
  • {1,2} has to be in domain of function
  • ...

Results:

naiveListableQ /@ {
  (3 - #)/(7*#) &,
  (3 - #)/(qq[7]*#) &,
  qq[(3 - #), (7*#)] &,
  Function[x, x + qq[5] + x/2],
  Function[x, qq[x + 5, x/2]],
  Function[, qq[(3 - #), (7*#)], Listable],
 }

{True, True, False, True, False, True}

share|improve this answer
    
I considered this approach and decided to go a different direction. It may be the most rigorous approach for anonymous functions that don't contain pattern matching. However, I don't like the fact that it does evaluate the function (multiple times) which works against the applications I have in mind. –  Mr.Wizard Sep 1 '13 at 13:54
    
@Mr.Wizard CW was intentional as it was bit too long for a comment. Except for the simplicity of it I don't like it either :) –  ssch Sep 1 '13 at 13:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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