# How to make a function with two patterns listable?

Suppose that I have a function that has two patterns:

disksConstantRadius[radius_][points_] := Disk[#, radius] & /@ points


(noting that this would be better---but less readable---as)

disksConstantRadii[radius_?NumericQ][points_ /; ArrayQ[points, 2,NumericQ]] :=


The above works just fine.

The objective is to make an operator form of Disk that operates on a list of points, but the question is more general.

Is there a name for this construction f[][]??

This is just idle curiosity (I clearly have a work-around), but would it be possible to make the function be Listable in its second argument?

I'm not surprised that this

Clear[disksConstantRadius];


doesn't work.

And also not surprised that this:

Clear[disksConstantRadius];


doesn't work either.

How could one construct an operator form disksConstantRadius[radius]?

There is a nice discussion about Listable here: The role and meaning of Listable, Leonid Shifrin, 2013

• "Listable" works for any nesting depth. That means your function would act on every coordinate separately. Therefore, you do not want a function, that should take a vector (e.g. a point) as input, to be listable. The way to go is using "Map" Aug 19, 2022 at 10:03
• The Map method is embodied in the first two examples which works just fine. Another solution is diskConstantRadii[r_] :=diskConstantRadii[r]= Compile[{{p,_Real,1}}, Evaluate[Disk[{Indexed[p,1].Indexed[p,1]},r],Attributes->Listable]. I’m just curious how one might do the f[][] version programmaticaly. My goal is to learn a new tick. Aug 19, 2022 at 10:43
• Edit, above comment should be {Indexed[p,1],Indexed[p,2]} Aug 19, 2022 at 10:49
• You can't make f listable if the basic call has the form f[{x_, y_}]. If f is listable, then f[{x, y}] becomes {f[x], f[y]} before any definitions for f are applied. It doesn't matter whether f is a symbol or a head like disksConstantRadius[r]. It can't be done via Listable. The restriction on subvalues is a red herring, and you have to use Map or Thread. Aug 20, 2022 at 14:34

Here's an alternative to Listable. It's somewhat the opposite to Listable, but it's also the opposite to unlistable. More like relistable: If given a simple list, change it to a list of lists.

ClearAll[disksConstantRadius];
Length@p == 2 :=
Last@Dimensions@pts == 2 :=


The conditions Length@p == 2 and Last@Dimensions@pts == 2 are somewhat optional depending on where you want the function call to fail, if it is called with data that are not coordinates of points in the plane.

Example:

disksConstantRadius[1][RandomReal[1, {3, 2}]]
(*
{Disk[{0.631657, 0.646406}, 1],
Disk[{0.223139, 0.962916}, 1],
Disk[{0.260601, 0.75212}, 1]}
*)


One thing that differs with the OP's description of the function is that disksConstantRadius always gives a list of disks, which might be an advantage in dealing with its output.

disksConstantRadius[1][{3, 7}]
(*
{Disk[{3, 7}, 1]}
*)


One might want to add a rule for an empty list, to mimic the standard behavior of Listable functions:

disksConstantRadius[radius_?NumericQ][{}] := {};

• Clever! Thanks. Aug 20, 2022 at 21:39

• I'd probably use f[x_][y_?MatrixQ]... if y is likely to be a medium to large packed array or f will be called a lot. Aug 20, 2022 at 14:26