Я думаю, что главное здесь заключается в том, что return()
предназначен для выхода из текущей области в родительскую область с определенным значением. В случае выполнения
return("hello")
# Error: no function to return from, jumping to top level
вы получаете ошибку, потому что мы вызываем ее из глобальной среды, и нет родительской области, к которой вы возвращаетесь. Обратите внимание, что благодаря отложенной оценке R параметры, передаваемые в функцию, обычно оцениваются в среде, из которой они были переданы. Таким образом, в этом примере
f <- function(x) x
f(return("hello"))
# Error in f(return("hello")) :
# no function to return from, jumping to top level
Так как мы фактически передаем вызов return()
функции из глобальной среды, то здесь результат будет оценен и вернет ту же ошибку. Но учтите, что это не то, что делает with
, вместо этого он захватывает передаваемые вами команды и повторно запускает их в новой среде. Это ближе к чему-то подобному
f <- function(x) eval(substitute(x))
f(return("hello"))
# [1] "hello"
Этот eval()
создает новый уровень области видимости, от которого мы можем выйти, и поскольку мы не оцениваем параметр, передаваемый функции напрямую, мы просто запускаем те Для команд в другой среде return
больше не оценивается в глобальной среде, поэтому ошибки нет. Таким образом, созданная нами функция в основном аналогична вызову
with(NULL, return("hello"))
# [1] "hello"
, который отличается от чего-то вроде
print(return("hello"))
# no function to return from, jumping to top level
, где параметр оценивается напрямую. Таким образом, различные значения return()
действительно являются побочными эффектами нестандартной оценки в этом случае.
Когда return()
используется внутри with()
, вы не возвращаетесь из функции, которую вы вызывали with()
from, но вы возвращаетесь из области, которую with()
создал для вас, чтобы запустить вашу команду.
Как исправить эту конкретную проблему, уже описано в комментариях, оставленных @IceCreamToucan. Вам просто нужно переместить возврат за пределы with()
.