你必须在R中定义一个函数的环境吗?

时间:2017-01-05 17:49:12

标签: r function scope environment

您是否必须在R中明确定义自定义函数的环境,还是在创建函数时自动“创建”(已定义?)?

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

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

我能想出的唯一一个简单的例子是函数内部的assign函数。

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

2 个答案:

答案 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

即使我们没有返回yassign()在我们指定的环境中创建了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.