Изменить вызов функции, захваченный в exp - PullRequest
0 голосов
/ 10 июня 2018

Например, изменение cumsum в выводе expr(cumsum(1:3)) на cumprod.

В настоящее время единственное, о чем я могу думать, - это преобразовать вывод expr(cumsum(1:3)) в строку, отредактировав ее, затем изменив его обратно на вызов функции.

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

library(rlang) 
f(expr(cumsum(1:4)), cumprod)
# [1] 1 2 6 24

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

Ответы [ 4 ]

0 голосов
/ 12 июня 2018

Мне нравится @David Arenburg, поэтому я публикую здесь его ответ и отмечаю его.

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

function f <- function(x, y) {
  tmp <- substitute(x) 
  tmp[[1]] <- substitute(y)  
  eval(tmp)
 }

и затем использовать его следующим образом

f(cumsum(1:4), cumprod) 
#[1] 1 2 6 24

- Дэвид Аренбург

0 голосов
/ 10 июня 2018

Вот вариант с использованием rlang

f <- function(ex, fn) {

   ex1 <- as.character(ex)
   fn <- enquo(fn)[-1]
   eval_tidy(parse_expr(glue::glue('{fn}({ex1[-1]})')))

   }
f(expr(cumsum(1:4)), cumprod)
#[1]  1  2  6 24
0 голосов
/ 10 июня 2018

Обратите внимание, что если вы замените cumsum на cumprod, то на выходе будет вектор 4, а не 24, поэтому мы предполагаем, что вы намеревались заменить его на prod.

Мы используем substitute для замены cumsum значением аргумента cumsum, а затем вычисляем полученное выражение.

f здесь не использует пакетов - входные данные вв вопросе используется expr от rlang, но даже в этом нет необходимости, поскольку мы могли бы использовать quote(...) вместо expr(...).

f <- function(.x, cumsum) eval.parent(do.call("substitute", list(.x)))

# test
f(expr(cumsum(1:4)), prod)
## [1] 24

f(expr(cumsum(1:4)), cumprod)
## [1]  1  2  6 24
0 голосов
/ 10 июня 2018

Если вы просто примените gsub к выражению R, оно преобразуется в символьный вектор и выполняет замену, которую вы можете привести как выражение с помощью parse:

y <- 1:4
x <- expression({cumsum(y)})

x.2 <- gsub("cumsum", "cumprod", x)
class(x.2)
# [1] "character"
x.2 <- parse(text = x.2)
eval(x)
# [1]  1  3  6 10
eval(x.2)
# [1]  1  2  6 24
...