1
$\begingroup$

This question already has an answer here:

I have a piece of code where I would like to do the something like the following:

ComposeList[Table[Which[
m < 3, f[#, m] &,
m < 6, f[#, m + 1] &
], {m, 1, 5, 1}], x]

The idea here is to repeatedly apply f to x, but with the second argument of f changing in some way as it goes. However, this does not work, because pure functions are left unevaluated. That means that the m in f[#,m] stays as m when the table is created, which is then meaningless later on.

If I try and fix this by wrapping f[#,m] in Evaluate, it evaluates not only m, but also f. This is a problem for me, because it tries to evaluate f with that Slot still in the first argument, and f is very complicated and it fails. I really need the resulting table to look like {f[#,1], f[#,2],...}.

The only solution I came up with is as follows:

ComposeList[Table[Which[
m < 3, f @@@ Function[Evaluate[qpzrqrq[#, m]]],
m < 6,  f @@@ Function[Evaluate[qpzrqrq[#, m + 1]]]
], {m, 1, 5, 1}], x]

Here I am evaluating the pure function with a different head (qpzrqrq) which I hope is not actually defined anywhere. This evaluates the arguments, and then I replaced qpzrqrq with the actual function f. However, this is definitely a hack, and relies on qpzrqrq being undefined. Does anyone have a better solution to this problem?

$\endgroup$

marked as duplicate by Mr.Wizard Jun 22 '15 at 23:42

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    $\begingroup$ It seems to me that Fold should be helpful to you. $\endgroup$ – MarcoB Jun 22 '15 at 12:24
4
$\begingroup$

One way is to use With

ComposeList[
 Table[
  With[{m = m}, Which[m < 3, f[#, m] &, m < 6, f[#, m + 1] &]],
  {m, 1, 5, 1}],
 x]
{x, f[x, 1], f[f[x, 1], 2], f[f[f[x, 1], 2], 4], f[f[f[f[x, 1], 2], 4], 5], 
 f[f[f[f[f[x, 1], 2], 4], 5], 6]}
$\endgroup$
  • $\begingroup$ Thank you! This is very helpful. $\endgroup$ – jmizrahi Jun 22 '15 at 14:12
3
$\begingroup$

This question is probably a duplicate of: Function in Table

If not I think you want FoldList:

FoldList[f, x, Table[If[m < 3, m, m + 1], {m, 5}]]
{x, f[x, 1], f[f[x, 1], 2], f[f[f[x, 1], 2], 4], f[f[f[f[x, 1], 2], 4], 5], 
 f[f[f[f[f[x, 1], 2], 4], 5], 6]}

As stated I think this is a duplicate but there may be methods applicable here that are not general. If f will not evaluate incorrectly when passed a literal # as an argument you could simply let the nascent Function bodies evaluate first, then make functions of them after:

ComposeList[
  Function /@ Table[If[m < 3, f[#, m], f[#, m + 1]], {m, 5}],
  x
]

You could also use Function itself to inject values:

ComposeList[Array[m \[Function] If[m < 3, f[#, m] &, f[#, m + 1] &], 5], x]

However if your problem is best solved by With[{m = m}, . . . I shall mark this as a duplicate, as it is the Accepted answer to the existing question.

$\endgroup$
  • 2
    $\begingroup$ Iversonian magic: m + Boole[m >= 3]. $\endgroup$ – J. M. will be back soon Jun 22 '15 at 12:52
  • $\begingroup$ Thanks. The problem with this solution is that my actual application is a little more complicated than the stripped down version I posted. Really the function statement is more like f[#,a,b,g[m],c,d,h[m]]. In other words, there are several arguments, some of which are dependent on the table index m. It's not obvious to me how to use FoldList to implement that. I'm guessing Sequence could be helpful, but I think the command would get pretty ugly. $\endgroup$ – jmizrahi Jun 22 '15 at 14:10
  • $\begingroup$ @jmizrahi Please see the update, and also tell me if you think this question should not be marked as a duplicate and why. $\endgroup$ – Mr.Wizard Jun 22 '15 at 21:52
  • $\begingroup$ I think you're right that it is a duplicate. The With solution solved my problem nicely. Thanks for your help! $\endgroup$ – jmizrahi Jun 22 '15 at 23:30
0
$\begingroup$

Use Evaluate

res1 =
 ComposeList[
  Table[
   Evaluate[Which[
      m < 3, f[#, m],
      m < 6, f[#, m + 1]]] &,
   {m, 5}],
  x]

{x, f[x, 1], f[f[x, 1], 2], f[f[f[x, 1], 2], 4], f[f[f[f[x, 1], 2], 4], 5], f[f[f[f[f[x, 1], 2], 4], 5], 6]}

res2 =
 ComposeList[
  Table[
   Evaluate[Piecewise[{
       {f[#, m], m < 3},
       {f[#, m + 1], m < 6}}]] &,
   {m, 5}],
  x]

{x, f[x, 1], f[f[x, 1], 2], f[f[f[x, 1], 2], 4], f[f[f[f[x, 1], 2], 4], 5], f[f[f[f[f[x, 1], 2], 4], 5], 6]}

res1 === res2

True

$\endgroup$

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