1

I wish to make custom listable function (for 2D points) with the next behaviour:

myf[{x_, y_}] := {doSmth@x, doSmth@y};
pts = {{x1,y1},{x2,y2}, ...};  
myf[pts] === {myf[{x1,y1}], myf[{x2,y2}], ...}

I'm going to do huge calculations, and read this in documentation:

To apply a function to a vector, take advantage of Listable functions when possible

And there is example that Listable without Map works ~10 times faster.

But when I set

Attributes[myf] = {Listable}

I get

 myf[pts] === {{myf[x1], myf[y1]}, {myf[x2], myf[y2]}, ...}

which is not what is needed ((

lesobrod
  • 1,657
  • 9
  • 14
  • 2
    Are you aware of this? – user1066 Oct 30 '23 at 11:38
  • @user1066, Hmm,I should think it over, but I'm not going to use some packed arrays – lesobrod Oct 30 '23 at 11:46
  • 3
    And the behavior you want can be easily achieved with Compile, but to use Compile properly we need to know what's that doSmth, so please make the question more specific. – xzczd Oct 30 '23 at 11:58
  • 1
    One usual trick is to pack a pair of {xk, yk} as a complex number zk := xk + yk I, then define a Listable function to be used on {z1, z2, ...}. – Silvia Oct 30 '23 at 19:42
  • if myf is already listable, it will automatically map. for example: ```myf = (#+1)*2&;

    myf@{{1,2},{3,4}}```

    – AsukaMinato Oct 31 '23 at 18:31

2 Answers2

2
pts = {{x1, y1}, {x2, y2}};

Just use Map:

Map[myf, pts]

{myf[{x1, y1}], myf[{x2, y2}]}

Or define

mf[x_] := Map[myf, x]

mf[pts]

{myf[{x1, y1}], myf[{x2, y2}]}

eldo
  • 67,911
  • 5
  • 60
  • 168
1
$Version

(* "13.3.1 for Mac OS X ARM (64-bit) (July 24, 2023)" *)

ClearAll["Global`*"]

Rather than use the attribute Listable, define myf as

myf[x_?VectorQ] := doSmth /@ x;

myf[x_List] := myf /@ x

Then

pts = Array[{x[#], y[#]} &, 4]

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

myf[pts]

(* {{doSmth[x[1]], doSmth[y[1]]}, {doSmth[x[2]], doSmth[y[2]]}, {doSmth[x[3]], doSmth[y[3]]}, {doSmth[x[4]], doSmth[y[4]]}} *)

Bob Hanlon
  • 157,611
  • 7
  • 77
  • 198