Search code examples
rlambdapurrranonymous-functionaccumulate

How to write a custom function directly inside purrr::accumulate2()


I am just trying my hands on lambda functions of purrr family.

Suppose I have to do some operation iteratively over result of previous iteration in vector through accumulate I can do it through .x and .y, where .x is result of application on previous element and .y is current element. Also assume that the function/iteration is 2x+3y i.e. double the previous result and add three times of current element, it can be done through like.

accumulate(1:10, ~2*.x + 3*.y)
 [1]    1    8   25   62  139  296  613 1250 2527 5084

#OR
accumulate(1:10, ~2*.x + 3*.y, .init = 2.5)
 [1]    2.5    8.0   22.0   53.0  118.0  251.0  520.0 1061.0 2146.0 4319.0 8668.0

However, I am not able to do so these type of iterations in accumulate2

accumulate2(1:5, 1:5, ~2*.x + 3*.y +.z)
Error in reduce2_impl(.x, .y, .f, ..., .init = .init, .acc = TRUE) : 
  `.y` does not have length 4

OR

accumulate2(1:5, 1:4, ~2*.x + 3*.y +.z)
Error in .f(out, .x[[x_i]], .y[[y_i]], ...) : object '.z' not found

What actually I understood from purrr::accumulate was that, it is a two argument function where first argument is result of previous iteration and second argument is vector passed into it directly. On similar lines accumulate2 is a three argument function where first argument is result of previous computation and other two arguments are passed directly.

Can someone tell where I am erring or am wrong in understanding the logic or what should be the correct way of doing it.


Solution

  • The .x and .y are only specified when there are two arguments. With more than 2, we can use ..1, ..2, ..3 in their order of occurrence

    library(purrr)
    accumulate2(1:5, 1:4, ~2*..1 + 3*..2 +..3)
    #[[1]]
    #[1] 1
    
    #[[2]]
    #[1] 9
    
    #[[3]]
    #[1] 29
    
    #[[4]]
    #[1] 73
    
    #[[5]]
    #[1] 165