gpt4 book ai didi

r - 如何在函数调用中将 `list2env()`(或通过管道传输到 `assign()`)?

转载 作者:行者123 更新时间:2023-12-05 02:48:19 24 4
gpt4 key购买 nike

我有一个用例,用于将函数映射到向量,然后将结果分配给父环境中的各个对象——不是全局环境,而是 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 创建于 2020-10-27 (v0.3.0)

最佳答案

最可靠也是最简单的方法是将函数的环境存储在一个名称中并引用该名称。

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
}

关于r - 如何在函数调用中将 `list2env()`(或通过管道传输到 `assign()`)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64555857/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com