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 With
s.
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!
(Composition @@ p /@ indexlist)@# // Expand
? $\endgroup$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 inCollect
. but thanks for the suggestion, I had forgotten aboutExpand
! :) $\endgroup$