tl; dr / summary
我有一个函数,它接受一个包含许多元素的列表作为参数。我希望能够通过在函数内分配这些元素来直接处理这些元素。由于我有许多元素,我想使用walk
包中的tidyverse
函数。
library(tidyverse)
list <- (a = 1, b = 2)
func <- function(x){
walk2(names(x), x, assign, envir = {some environment})
{Rest of the function, where I can use a and b instead of x$a and x$b}
}
我应该使用什么环境?并且parent.frame()
没有不工作,请参阅下文。
为什么parent.frame()无法正常工作
第1步:没有函数 - 这里需要parent.frame()(因为你在函数中使用了assign)。但如果你这样做,一切正常。
x <- list(a = 1, b = 2)
a <- 0
b <- 0
# Doesn't work:
walk2(names(x), x, assign)
a
b
# Does work:
walk2(names(x), x, assign, envir = parent.frame())
a
b
第2步:一个功能 - 当你在一个函数中做同样的事情时,事情会变得更复杂。使用parent.frame()
作为环境也会导致变量在全局环境中发生变化。
func <- function(x) {
walk2(names(x), x, assign)
print(paste0("a inside func without parent.frame() is ", a))
print(paste0("b inside func without parent.frame() is ", b))
walk2(names(x), x, assign, envir = parent.frame())
print(paste0("a inside func with parent.frame() is ", a))
print(paste0("b inside func with parent.frame() is ", b))
}
# Using envir = parent.frame() seems to work at first
x <- list(a = 1, b = 2)
a <- 0
b <- 0
func(x)
# But a and b get overwritten in the global environment as well (unwanted)
a
b
这是不可取的。当您在&#34; normal&#34;中分配时,不会发生这种情况。方式如下例所示。
# How it should work
func_desired <- function(x){
a <- x[[1]]
b <- x[[2]]
print(paste0("a inside func_alt is ", a))
print(paste0("b inside func_alt is ", b))
}
# a and b are correctly assigned within the function
x <- list(a = 1, b = 2)
a <- 0
b <- 0
func_desired(x)
# But outside of the function a and b are not altered
a
b
第3步:嵌套函数 - 这里很明显,使用parent.frame()
将分配不在调用walk
的环境中的变量,而是在其后面的变量。
func2 <- function(x){
func(x)
print(paste0("a inside func2 is ", a))
print(paste0("b inside func2 is ", b))
}
# a and b are assigned 1 and 2 inside func2,
# But in the global environment they stay unchanged (both 0)
# func (called from func2) will look in the global environment and find a = b = 0
x <- list(a = 1, b = 2)
a <- 0
b <- 0
func2(x)
a
b
我的问题
我应该使用什么环境才能使其按预期工作,即所有变量都分配给列表中的名称,但仅限于调用walk
的函数的环境中。?