Вот как я бы кодировал myfun()
:
myfun <- function(a, b, data) {
eval(substitute(a + b), envir=data, enclos=parent.frame())
}
myfun(mpg, hp, mtcars)
# [1] 131.0 131.0 115.8 131.4 193.7 123.1 259.3 86.4 117.8 142.2 140.8 196.4
# [13] 197.3 195.2 215.4 225.4 244.7 98.4 82.4 98.9 118.5 165.5 165.2 258.3
# [25] 194.2 93.3 117.0 143.4 279.8 194.7 350.0 130.4
Если вы знакомы с with()
, интересно увидеть, что он работает почти точно так же:
> with.default
# function (data, expr, ...)
# eval(substitute(expr), data, enclos = parent.frame())
# <bytecode: 0x016c3914>
# <environment: namespace:base>
В обоих случаях основная идея заключается в том, чтобы сначала создать выражение из символов, переданных в качестве аргументов, а затем оценить это выражение, используя data
в качестве «среды» оценки.
Первоечасть (например, превращение a + b
в выражение mpg + hp
) возможно благодаря substitute()
.Вторая часть возможна, потому что eval()
был красиво спроектирован, так что он может принять data.frame
в качестве среды оценки.