Частично оценивать выражение при выполнении нестандартной оценки в R - PullRequest
4 голосов
/ 29 мая 2019

Я копаю голову в нестандартных механизмах оценки R. На полпути я все еще время от времени застреваю. ; -)

Я сделал немного calculator, которое красиво печатает вычисление вместе с результатом:

calculator <- function(e) cat(deparse(substitute(e)), "=", e)

Это отлично работает:

calculator(1 + 2)

печать:

1 + 2 = 3

Однако при вызове calculator с:

a <- 1; b <- 2
calculator(a + b)

вывод:

a + b = 3

Как настроить calculator, чтобы он печатал 1 + 2 = 3 и в последнем случае?


Я пытался:

calculator2 <- function(e) {
  ex <- lapply(substitute(e), function(x) ifelse(is.numeric(x), eval(x), x))
  cat(deparse(ex), "=", e)
}

calculator2(1 + 2)
# list(+, 1, 2) = 3
calculator2(a + b)
# list(+, a, b) = 3

Это, очевидно, не работает. После звонка lapply у меня есть список и cat выводит list(+, 1, 2) на консоль.

Итак, я сделал еще одну попытку:

calculator3 <- function(e) {
  ex <- substitute(e)
  for(i in 1:length(ex)) {
    if(is.numeric(ex[[i]])) ex[[i]] <- eval(ex[[i]])
  }
  cat(deparse(ex), "=", e)
}

calculator3(1 + 2)
# 1 + 2 = 3
calculator3(a + b)
# a + b = 3

.. что совпадает с моей первой версией ..

1 Ответ

6 голосов
/ 29 мая 2019

Это работает для выражения с одним оператором.Для более сложных выражений (которые являются вызовами вложенных функций) вам необходимо использовать рекурсию вместо простых циклов.

a <- 1; b <- 2
calculator1 <- function(e) {
  expr <- substitute(e)
  evalexpr <- lapply(expr, eval) #evaluate each part of expression
  numind <- vapply(evalexpr, is.numeric, FUN.VALUE = logical(1))
  expr[numind] <- evalexpr[numind]
  cat(deparse(expr), "=", e)
}

calculator1(a + b)
#1 + 2 = 3
calculator1(1 + 2)
#1 + 2 = 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...