Playing with rlang
package - Removing the pipe operator
- I’m trying to wrap my head around some parts of the
rlang
package so I
set myself a task to focus my exploration: Auto-rewrite a chain of piped functions as a set of nested function calls
unpipe
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# unpipe - rewrite a chain of piped functions as a set of nested function calls
#
# A recursive function that descends through the language tree and flips
# arguments
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
unpipe <- function(ee) {
if (!rlang::is_call(ee)) {
return(ee)
}
this_fn <- rlang::call_name(ee)
updated_args <- rlang::call_args(ee) %>% map(unpipe)
if (identical(this_fn, "%>%")) {
lhs <- updated_args[[1]]
rhs <- updated_args[[2]]
if (rlang::is_call(rhs)) {
rlang::call2(call_name(rhs), !!!c(lhs, call_args(rhs)))
} else {
rlang::call2(rhs, lhs)
}
} else {
rlang::call2(this_fn, !!!updated_args)
}
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Improbable test chain with a variety of lhs/rhs arguments to a pipe
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
chain <- quote(
1:3 %>%
mean(na.rm=TRUE) %>%
print %>%
filter(hello == median(zz))
)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# unpipe this chain
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
chain
1:3 %>% mean(na.rm = TRUE) %>% print %>% filter(hello == median(zz))
unpipe(chain)
filter(print(mean(1:3, na.rm = TRUE)), hello == median(zz))