您必须在 R 中定义函数的环境吗?

Do you have to define the environment of a function in R?

您是否必须在 R 中显式定义自定义函数的环境,还是在创建函数时自动 "created"(定义?)?

我想知道创建一个函数是否会自动在所述函数内创建一个环境,或者是否需要显式创建环境。如果前者为真(即环境是自动创建的),我该如何明确引用它?

我必须首先为所述函数创建一个新环境(即,通过使用 new.env 分配一个新环境)还是我可以简单地使用一些其他语法(可能类似于“current.env()”) ?

我能想出的唯一使用它的简单示例是函数内部的 assign 函数。

function(a,b) {
  assign(paste(a,b,sep='.'), 'help me', envir = ONLY CURRENT FUNCTION)
}

不要在作业中提及环境。

 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 和 returns 它的值:

> 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.

如果您必须明确提及它,而您没有必要,那就不要,除非您能给我们一个 真正好的 为什么您必须这样做的理由,然后复制 assign 的作用:

> foo = function(a,b){assign(paste(a,b,sep="."),99,envir=as.environment(-1));ls()}
> foo("fnord","fnord")
[1] "a"           "b"           "fnord.fnord"

或复制其他人在这里所说的话:

> foo = function(a,b){assign(paste(a,b,sep="."),99,envir=environment());ls()}
> foo("bubble","gum")
[1] "a"          "b"          "bubble.gum"

当前环境由environment()return编辑:

> 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() 是从我的工作区调用的,所以全局环境是 returned。但是,如果我们从另一个函数内部调用 bar(),我们会得到 that 函数的环境,因为它现在是调用环境:

> 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

即使我们没有 return yassign() 在我们指定的环境中创建了 y

需要强调的是,很少有人会像这样 assign() 分配到其他环境中。一个主要原因是现在你的函数有副作用,而 R 是一种函数式语言,通过让函数接受输入和 return 输出而不影响任何其他东西,更容易推断代码的工作方式。因此你更喜欢

foo1 <- function(x) {
  y <- x
  y
}

y <- foo1(x)

超过

foo2 <- function(x, varname) {
  assign(varname, x, envir = parent.frame())
  invisible()
}

foo2(x, "y")

因为我知道调用 foo1() 没有副作用,它只是接受一些输入并 return 输出。这有点做作,因为您选择了 assign() 但这将广泛适用。这也是复杂列表或其他类型的对象从许多 R 函数中 return 编辑的原因,尤其是那些适合模型的函数。