6
$\begingroup$

This question is closely related to questions 83720, 17460, and 11298.

How would you write the operator

F = Through[#1[#2]] &

in the prettiest, fastest, or most poetic way? It just looks clumsy the way I've written it.

Also, can you think of any pitfalls? Edge cases where this function does not behave regularly?

What F does is to apply a list of functions to a list of values:

F[{Sin, Cos, Tan}, {x, y}]
(*    {{Sin[x], Sin[y]}, {Cos[x], Cos[y]}, {Tan[x], Tan[y]}}    *)

benchmarks of solutions

Here's a benchmark of all solutions, sorted from fastest to slowest.

(* random functions and random data *)
a = Table[Function[x, Evaluate[x + RandomReal[]]], {10^4}];
b = RandomReal[{0, 1}, 10^4];

original post: very fast

F = Through[#1[#2]] &;
c0 = F[a, b]; // AbsoluteTiming // First
(*    0.506063    *)

contracted syntax: a little bit slower

F = Through@*Construct;
c1 = F[a, b]; // AbsoluteTiming // First
(*    0.85128    *)

dataset query: still a bit slower

F = Query[#1][#2] &;
c2 = F[a, b]; // AbsoluteTiming // First
(*    1.45958    *)

explicit outer-product construction: terribly slow

F = Outer[Construct, ##] &;
c3 = F[a, b]; // AbsoluteTiming // First
(*    83.0245    *)

check that all solutions agree on the result:

c0 == c1 == c2 == c3
(*    True    *)
$\endgroup$
2
  • 4
    $\begingroup$ There is one pitfall you have to be aware of, which is that you're relying on your functions to be Listable in the examples you're giving (Cos, Sin and Tan). For a list of non-listable functions you'd need F = Through[(Map /@ #1)[#2]] &. $\endgroup$ Jun 10, 2019 at 13:20
  • $\begingroup$ Thanks @SjoerdSmit! Yes that's a very important one. $\endgroup$
    – Roman
    Jun 10, 2019 at 13:26

2 Answers 2

6
$\begingroup$

To streamline the syntax of F = Through[#1[#2]]& we can do

F = Through@*Construct

Alternatively, an explicit outer product:

F = Outer[Construct, ##] &
$\endgroup$
5
  • $\begingroup$ What is the purpose or function of * here? $\endgroup$ Jun 10, 2019 at 13:16
  • 1
    $\begingroup$ @CATrevillian operator composition $\endgroup$
    – Roman
    Jun 10, 2019 at 13:22
  • $\begingroup$ sweet!! That’s awesome as all get-out! Many thanks. Side note: does any resource exist of just these shorthand inputs? They’re my favourites $\endgroup$ Jun 10, 2019 at 13:31
  • 1
    $\begingroup$ @CATrevillian Here's the list of all operator input forms sorted by precedence. $\endgroup$
    – Roman
    Jun 10, 2019 at 13:40
  • $\begingroup$ +1, ro-man, +1 :) $\endgroup$ Jun 10, 2019 at 13:42
3
$\begingroup$

Using Comap: (since v14.0, 2023)

Comap[{Sin, Cos, Tan}, {x, y}]

{{Sin[x],Sin[y]},{Cos[x],Cos[y]},{Tan[x],Tan[y]}}

$\endgroup$
2
  • $\begingroup$ Thanks. Is it competitive performance-wise? $\endgroup$
    – chris
    Mar 25 at 6:49
  • 1
    $\begingroup$ The Comap is slower by a factor of 15.5 compare to F = Through@*Construct. @chris $\endgroup$
    – Syed
    Mar 25 at 6:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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