您是否必须在R中明确定义自定义函数的环境,还是在创建函数时自动“创建”(已定义?)?
我想知道创建一个函数是否会自动在所述函数中创建一个环境,或者是否需要显式创建环境。如果前者为真(即自动创建环境),我该如何明确引用它?
我必须首先为所述函数创建一个新环境(即,通过使用new.env
分配新环境)或者我可以简单地使用其他语法(可能类似“current.env()
”)吗? / p>
我能想出的唯一一个简单的例子是函数内部的assign
函数。
function(a,b) {
assign(paste(a,b,sep='.'), 'help me', envir = ONLY CURRENT FUNCTION)
}
答案 0 :(得分:7)
当前环境由environment()
返回:
> environment()
<environment: R_GlobalEnv>
> foo <- function() environment()
> foo()
<environment: 0x1391b88>
> foo()
<environment: 0x1391f08>
> foo()
<environment: 0x1392288>
> foo()
<environment: 0x13916a0>
请注意,对foo()
的每次调用都有不同的环境,因为您调用的环境仅在调用函数时创建。
要获取调用函数的封闭框架,请使用parent.frame()
:
> bar <- function() parent.frame()
> bar()
<environment: R_GlobalEnv>
从我的工作区调用bar()
时,将返回全局环境。但是,如果我们从另一个函数内部调用bar()
,我们将获得 函数的环境,因为它现在是调用环境:
> foobar <- function() { print(environment()); bar() }
> foobar()
<environment: 0x74a7d68>
<environment: 0x74a7d68>
如果我们查看您的assign()
示例,如果您想要当前环境,则不必告诉它使用哪个环境,因为默认情况下它是如何设置的。但是,如果你想明确这个,你可以使用:
foo <- function(x) {
assign("y", x, envir = environment())
y # return(y) to show it is assigned `x`
}
哪个给出了
> foo(20)
[1] 20
> foo(10)
[1] 10
> foo("a")
[1] "a"
如果要在父框架中指定,只需传递envir = parent.frame()
:
foo <- function(x) {
assign("y", x, envir = parent.frame())
"not returning `y`" # return something else
}
给出了
> ls()
[1] "bar" "foo" "foobar"
> foo(20)
[1] "not returning `y`"
> ls()
[1] "bar" "foo" "foobar" "y"
> y
[1] 20
即使我们没有返回y
,assign()
在我们指定的环境中创建了y
。
重要的是要强调尽管很少应该这样做assign()
,但要分配到其他环境中。这样做的一个主要原因是,现在你的函数有副作用,而R是一种函数式语言,通过函数获取输入和返回输出更容易推理代码的工作原理,而不会影响其他任何东西。因此你更喜欢
foo1 <- function(x) {
y <- x
y
}
y <- foo1(x)
在
foo2 <- function(x, varname) {
assign(varname, x, envir = parent.frame())
invisible()
}
foo2(x, "y")
因为我知道调用foo1()
没有副作用,它只是输入一些输入并返回输出。这有点人为,因为你选择assign()
,但这将广泛应用。这也是许多R函数返回复杂列表或其他类型对象的原因,尤其是那些适合模型的函数。
答案 1 :(得分:0)
请勿在转让中提及环境。
}
{
没有任何名为},
{
:
foo = function(a,b){
assign(paste(a,b,sep="."),99)
return(hey.you) # note this is hard coded here...
}
我致电hey.you
,创建> ls()
[1] "foo"
并返回其值:
foo
但不会弄乱我的环境因为它是在函数环境中创建的:
hey.you
因为这是默认设置。
> foo("hey","you")
[1] 99
如果你明确地提到它,并且你不必这样做,那么除非你能给我们一个真正好的理由,为什么你必须这样做,那么只需复制分配的内容:
> ls()
[1] "foo"
或者复制其他人在这里说的话:
?assign
pos: where to do the assignment. By default, assigns into the
current environment. See ‘Details’ for other possibilities.