如何解决如何在函数调用中使用“ list2env”或传递到“ assign”?
我有一个用例,用于将函数映射到向量,然后将结果分配给父环境(不是全局环境,而是调用map()
的环境)中的单个对象。具体来说,这都是在函数内发生的,因此我想将这些对象分配给函数环境,以供以后在函数调用内使用。
我了解您可以通过以下方式指定环境:以数字位置递增,全局值为1,或者从当前环境倒数,即使用rlang::caller_env()
。但是,无论哪种方法,在这种情况下,我都没有可靠的方法来指定所需的函数执行环境。如下面的reprex所示,我可以使用rlang::caller_env(6)
使它在一种特定情况下工作,但是很明显,在这种情况下,精确计数6帧恰好可以工作,它具有特定的管道链和操作顺序,并且任何情况下都可能有其他需要的值-通过在函数中打印回溯,我才发现6是正确的数字。使用map()
时,它是13左右,可能是由于map()
中所有嵌套的函数调用。而且我无法使用list2env()
所以我要寻找的是我可以提供给list2env()
或assign()
的一些论点,这些论点将明确且始终如一地导致分配在我所使用的函数环境中发生即使在管道链的末尾调用这些函数,也可以在其中使用它们。
library(tidyverse)
library(rlang,warn.conflicts = FALSE)
## Trying to assign the value 'foo' to an object named 'bar' in a specific
## location
# Fails because `bar` is assigned in the pipe execution evironment
'foo' %>% assign(x = 'bar')
exists('bar')
#> [1] FALSE
# Works because `pos = 1` refers specifically to the global environment
'foo' %>% assign(x = 'bar',pos = 1)
exists('bar')
#> [1] TRUE
rm(bar)
# Works because assign isn't in a pipe,and its special,default `pos` of
# `-1` refers to the function execution environment,as desired
exec(function() {
assign('bar','foo')
exists('bar',inherits = FALSE)
})
#> [1] TRUE
rm(bar)
#> Warning in rm(bar): object 'bar' not found
# Fails because the function's exec. env. is "overshot," and the assignment
# occurs in the global environment instead; no numeric position seems to work
exec(function() {
'foo' %>% assign(x = 'bar',pos = 1)
exists('bar',inherits = FALSE)
})
#> [1] FALSE
rm(bar)
# Works,presumably because the function's exec. env. happens to be exactly 6
# frames back from the environment in which the `assign()` call is evaluated,in
# this specific case
exec(function() {
'foo' %>% assign(x = 'bar',pos = caller_env(6))
print(exists('bar',inherits = FALSE))
print(bar)
})
#> [1] TRUE
#> [1] "foo"
# Fails for unkNown reasons - maybe there's a `caller_env()` value that would
# work,but I haven't found it
exec(function() {
list <- list(bar = 'foo')
list2env(list,envir = caller_env())
exists('bar',inherits = FALSE)
})
#> [1] FALSE
由reprex package(v0.3.0)于2020-10-27创建
解决方法
最可靠的和最简单的方法是将函数的环境存储在名称中并引用该名称。
f = function () {
env = environment()
'foo' %>% assign('bar',envir = env)
foo
}
如果您不使用管道,则list2env
可直接工作:
g = function () {
list = list(foo = 'bar')
list2env(list,envir = environment())
foo
}
但是在两种情况下,我通常都会建议使用列表,并避免将变量分配给调用环境。以下等同于g
:
g2 = function () {
list = list(foo = 'bar')
list$foo
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。