# MapThread a function with last result as input

I am trying to improve some pieces of coding I use frequently and am stuck with the following. I suspect there is a very similar answer but was unable to find it.

Function fun with 3 arguments "walks" over three lists of equal length (contained in sp). The 4th argument a is the value of the function in the last step. Essentially, I want to MapThread at position I across the length of the lists while also using the last evaluation. I tried to use Fold or Nest together with Reap/Sow but to no avail. The output is the evaluation of the function, and a working example with a Do loop is as follows.

sp = RandomInteger[{1, 10}, {3, 10}]
fun[{x_, y_, z_, a_}] := 2 x - y + 3 z - 2 a
atposI = 0; lastval := 0; output := {};

Do[{
atposI = Append[sp[[All, i]], lastval];
lastval = fun[atposI];
output = Append[output, lastval]
}, {i, 1, 10}]
output


Input:

{{7, 1, 5, 10, 10, 2, 5, 10, 10, 6}, {4, 1, 4, 2, 5, 2, 2, 4, 8, 10}, {2, 6, 1, 4, 6, 7, 4, 1, 2, 8}}

Result

{16, -13, 35, -40, 113, -203, 426, -833, 1684, -3342}

I am particularly interested in solutions that contain Fold, Nest and Reap/Sow, although any answer is more than welcome.

• FoldPairList does this, or similar enough, if I understand your question right. May 5 '20 at 17:41

An alternative to FoldList could be FoldPairList:

FoldPairList[
Function[{prev, new}, {#, #}&@ ({2, -1, 3}.new - 2 prev) ],
0,
Transpose@sp
]

(* {16, -13, 35, -40, 113, -203, 426, -833, 1684, -3342} *)


In response to the request of keeping function fun definition, you can modify the above to obtain the same result as follows:

ClearAll[fun]
fun[{x_, y_, z_, a_}] := 2 x - y + 3 z - 2 a

FoldPairList[
Function[{prev, new}, {#, #}&@ fun[{Sequence @@ new, prev}]],
0,
Transpose@sp
]

• Many thanks for your answer. As I commented to another post, is it possible to retain function fun "as is" in the code and not rely on it being linear and use the coefficients? May 5 '20 at 19:00
• @Titus Sure, although it may be a bit awkward-looking. See edit. May 5 '20 at 19:15

Indeed, FoldList[] would be the appropriate operation here:

FoldList[{2, -1, 3, -2}.Append[#2, #1] &, 0,
Transpose[{{7, 1, 5, 10, 10, 2, 5, 10, 10, 6},
{4, 1, 4, 2, 5, 2, 2, 4, 8, 10},
{2, 6, 1, 4, 6, 7, 4, 1, 2, 8}}]] // Rest
{16, -13, 35, -40, 113, -203, 426, -833, 1684, -3342}


Of course, modifying the snippet above to use fun[] in the OP is not too hard to do (spot the difference!):

FoldList[fun[Append[#2, #1]] &, 0,
Transpose[{{7, 1, 5, 10, 10, 2, 5, 10, 10, 6},
{4, 1, 4, 2, 5, 2, 2, 4, 8, 10},
{2, 6, 1, 4, 6, 7, 4, 1, 2, 8}}]] // Rest

• Many thanks for an elegant answer. I would just like to note that my function is a toy function which will be replaced by something complicated. How would your answer change if fun had to be used "as is", i.e. without using the {2, -1, 3, -2}.Append[#2, #1] & structure? May 5 '20 at 18:59
• See the edited version. May 6 '20 at 0:22
foldList = Rest @* FoldList[fun @* Flatten @* Reverse @* List] @* Prepend[0] @* Transpose;


Example:

sp = {{7, 1, 5, 10, 10, 2, 5, 10, 10, 6}, {4, 1, 4, 2, 5, 2, 2, 4, 8, 10},
{2, 6, 1, 4, 6, 7, 4, 1, 2, 8}};

foldList @ sp

{16, -13, 35, -40, 113, -203, 426, -833, 1684, -3342}


Also

foldList2 = Transpose /* Prepend[0] /* FoldList[fun @* Flatten @* Reverse @* List] /* Rest

foldList2 @ sp

 {16, -13, 35, -40, 113, -203, 426, -833, 1684, -3342}