0
$\begingroup$

So, I'm dealing with iterated polynomials of a single variable—say they're anonymous functions labeled as $p_i$, i.e. p[1], p[2], etc., and that these have explicit definitions. I'd like to compose a list of these, collect the terms, and then make the result an anonymous function. So, one way I have of doing this, with some example polynomials, is

indexlist0 = {1, 3, 2};
p[1] = (#^2 + 1 &);
p[2] = (#^3 + 3 # - 1 &);
p[3] = (5 # - 2 &);

polycompose1[indexlist_List] := Construct[Function, Collect[(Composition @@ p /@ indexlist)[#], #]]

polycompose1[indexlist0]

(* Out: 50 - 210 #1 + 225 #1^2 - 70 #1^3 + 150 #1^4 + 25 #1^6 & *)

(* Contrast with Composition @@ p /@ indexlist0,
   which gives simply (#1^2 + 1 &)@*(5 #1 - 2 &)@*(#1^3 + 3 #1 - 1 &). *)

I'm a bit worried about whether the unbound Slot could "leak" somehow, or maybe get bound by some other Function in some contexts before it has a chance to get bound by the Function in Construct.

Another way I have of doing this is

polycompose2[indexlist_List] := Block[{x}, 
 With[{body = Collect[(Composition @@ p /@ indexlist)[x], x]}, 
  Function[x, #] & @ body]]

Block[{a},
  polycompose1[indexlist0][a] === polycompose2[indexlist0][a]]

(* Out: True *)

This seems safer, but again, I'm not sure if one is better than the other, especially if I'm doing this many times and want to avoid unnecessary Withs.

EDIT: Yet another way is

polycompose3[indexlist_List] := 
 MapAt[Evaluate, 
  Function[Collect[(Composition @@ p /@ indexlist)[#], #]], 1]

polycompose3[indexlist0] === polycompose1[indexlist0]

(* Out: True *)

from this answer, which I like quite a bit, and feels "safe". But is it?

So, my questions are:

  • Is there anything actually "unsafe" about polycompose1? (Or, for that matter, either of the other two options?) It seems there might be, but I'm not sure.

  • Are there any other ways to accomplish this (esp. if they're "safer" or more efficient)?

This question is primarily about the safest way to do this, and more specifically whether the first option can be realized as unsafe, not about simply finding a way to accomplish the task per se. (So, just to pre-empt it, I don't think this is a duplicate.)

Thanks!

$\endgroup$
2
  • $\begingroup$ Why not (Composition @@ p /@ indexlist)@# // Expand? $\endgroup$
    – Somos
    Commented May 28, 2021 at 23:04
  • $\begingroup$ @Somos hmm, yeah, I guess I could use that instead of Collect[(Composition @@ p /@ indexlist)[#], #]! but I'm more wondering about whether # is leaky there, and I don't think I'm composing so many polynomials that I'll need to worry about efficiency in Collect. but thanks for the suggestion, I had forgotten about Expand! :) $\endgroup$
    – thorimur
    Commented May 29, 2021 at 21:24

0

Your Answer

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

Browse other questions tagged or ask your own question.