Вам нужно всего лишь сделать одно изменение, чтобы ваш пример работал - переопределите вашу функцию, чтобы использовать substitute()
, чтобы «исправить» нужные значения в пределах f()
:
f <- function(env,z) {
eval(substitute(x+z,list(z=z)), env)
}
Это может быстро стать темным, особенно если учесть, что вы даже можете включить операторы присваивания в substitute()
(например, заменить x+z
на y <- x+z
, но это не совсем уместно), но этот выбор может сделать разработчик ...
Кроме того, вы можете заменить list(z=z)
в приведенном выше выражении подстановки на environment()
(например, substitute(x+z,environment())
), если у вас нет конфликтующих имен переменных между теми, которые переданы в f()
, и теми, которые находятся в вашем 'env', но, возможно, вы не захотите заходить слишком далеко.
Редактировать: Вот два других способа, первый из которых предназначен только для демонстрации гибкости в манипулировании средами, а второй более целесообразно использовать.
1) изменить окружающее окружение 'env' (но перед выходом из функции изменить его на исходное значение):
f <- function(env,z) {
e <- environment(env)
environment(env) <- environment()
output <- with(env,x+z)
environment(env) <- e
output
}
2) Принудительно вычислять 'z' в текущей среде функции (используя environment()
), вместо того, чтобы оставить его свободной переменной после вычисления выражения x+z
в 'env'.
f <- function(env,z) {
with(environment(),with(env,x+z))
}
В зависимости от желаемого порядка разрешения, в случае противоречивых ассоциаций символ-значение - например, если у вас есть «x», определенное как в вашей функциональной среде, так и в среде, которую вы создали, «y» (какое значение «x» делает вы хотите, чтобы это предполагалось?) - вместо этого вы можете определить тело функции как with(env,with(environment(),x+z))
.