Вызовите функцию много раз, не дублируя ее (с%>%)

Давайте предположим, что у нас есть 3 функции с этой минимальной функциональностью:

func1 <- function (x) {
  x + 1
}

func2 <- function (x, plus = T) {
  if (plus == TRUE) {
    x + 2
  } else {
    x - 5 
  }
}

func3 <- function (x) {
  x + 3
}

Я хотел бы вложить эту функцию друг в друга, как это с оператором трубы (%>%):

library(magrittr)

func1(0) %>% func2(plus = T) %>% func2(plus = F) %>% func3
# result: 1

Какая эквивалентная версия этого:

func3(func2(func2(func1(0), plus = T), plus = F))
# result: 1

Я пытаюсь найти метод, который не требует дублирования функции func2() (потому что мне приходится многократно запускать ее, а также я хотел бы динамически изменять количество вызовов функции и параметра). В настоящее время я не большой специалист по прикладным функциям или пакетам карт, но я думаю, что по крайней мере один из них может сделать эту работу.

Это, конечно, просто пример, мой реальный код намного сложнее, я просто пытаюсь упростить мою проблему, чтобы найти решение.

Мне приходится пользоваться оператором трубопровода, поэтому меня интересуют только те решения, которые также работают с трубами.

2 ответа

Решение

Напишите функцию, которая принимает начальный x и результаты, чтобы накормить func2 и проходит через эти результаты:

func2_iterate = function(x, outcomes){
  for (i in 1:length(outcomes)){
    x = func2(x, outcomes[i])
  }
  return(x)
}

Тогда беги (с func1, func2, func3 как указано выше):

func1(0) %>% func2_iterate(c(T, F)) %>% func3
#result: 1

Я также хотел бы отметить, что в данном конкретном случае выход func2_iterate это просто вход, плюс 2 раз количество T в outcomesминус 5 раз количество F в outcomes, Но я предполагаю, что у вас действительно есть функции, которые делают что-то более сложное.

Используя partial / compose / invoke комбо:

library(tidyverse)
f2b <- invoke(compose, map(c(F,T), ~substitute(partial(func2, plus =.), lst(.))))

func1(0) %>% f2b %>% func3
# [1] 1
Другие вопросы по тегам