简体   繁体   English

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

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

Do you have to explicitly define the environment of a custom function in R, or is it automatically "created" (defined?) when a function is created? 您是否必须在R中显式定义自定义函数的环境,还是在创建函数时自动“创建”(定义?)?

I want to know if creating a function automatically creates an environment within said function or whether the environment needs to be explicitly created. 我想知道是否创建函数会自动在所述函数内创建环境,或者是否需要显式创建环境。 If the former is true (ie, the environment is automatically created), how do I explicitly refer to it? 如果前者是正确的(即,环境是自动创建的),我如何显式引用它?

Must I first create a new environment for said function (ie, by assigning a new environment using new.env ) or can I simply use some other syntax (perhaps something like " current.env() ")? 我必须首先为上述函数创建一个新环境(即,通过使用new.env分配一个新环境)还是可以简单地使用其他语法(例如“ current.env()类的东西current.env() ”?

The only simple example I can come up with that would use this is assign functions inside the function. 我可以使用的唯一简单示例就是在函数内部assign函数。

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

The current environment is returned by environment() : 当前环境由environment()返回:

> environment()
<environment: R_GlobalEnv>
> foo <- function() environment()
> foo()
<environment: 0x1391b88>
> foo()
<environment: 0x1391f08>
> foo()
<environment: 0x1392288>
> foo()
<environment: 0x13916a0>

Notice that each call to foo() has a different environment as the environment you are thinking about only gets created when the function is called. 注意,对foo()每次调用都具有不同的环境,因为您正在考虑的环境仅在调用函数时才创建。

To get the enclosing frame, where the function was called from, use parent.frame() : 要获取从中调用函数的封闭框架,请使用parent.frame()

> bar <- function() parent.frame()
> bar()
<environment: R_GlobalEnv>

As bar() was called from my workspace, the global environment is returned. 从我的工作区调用bar()时,将返回全局环境。 But, if we call bar() from inside another function, we get the environment of that function as that is now the calling environment: 但是,如果我们从另一个函数内部调用bar() ,则会得到该函数的环境因为它现在是调用环境:

> foobar <- function() { print(environment()); bar() }
> foobar()
<environment: 0x74a7d68>
<environment: 0x74a7d68>

If we look at your assign() example, you don't have to tell it which environment to use if you want the current environment as that is how it is setup to work by default. 如果我们看一下您的assign()示例,那么如果您想要当前环境,则不必告诉它使用哪个环境,因为默认情况下这就是它的设置方式。 But, if you wanted to be explicit about this you'd use: 但是,如果您想对此进行明确说明,可以使用:

foo <- function(x) {
  assign("y", x, envir = environment())
  y # return(y) to show it is assigned `x`
}

Which gives 这使

> foo(20)
[1] 20
> foo(10)
[1] 10
> foo("a")
[1] "a"

If you want to assign in the parent frame, just pass envir = parent.frame() : 如果要在父框架中分配,只需传递envir = parent.frame()

foo <- function(x) {
  assign("y", x, envir = parent.frame())
  "not returning `y`" # return something else
}

which gives 这使

> ls()
[1] "bar"    "foo"    "foobar"
> foo(20)
[1] "not returning `y`"
> ls()
[1] "bar"    "foo"    "foobar" "y"     
> y
[1] 20

Even though we didn't return y , the assign() created y in the environment we specified. 即使我们没有返回yassign()在我们指定的环境中也创建了y

It is important to stress though that rarely should one be doing assign() like this, to assign into other environments. 需要强调的是,尽管很少有人会像这样进行assign()分配到其他环境,这一点很重要。 A major reason for this is that now your function has side effects and R is a functional language where it is easier to reason about how code works by having a function take inputs and return outputs, without affecting anything else. 造成这种情况的主要原因是,现在您的函数具有副作用,R是一种函数语言,在这种语言中,通过使函数接受输入和返回输出而又不影响任何其他函数,可以更容易地推断代码的工作方式。 Hence you would prefer 因此,您宁愿

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

y <- foo1(x)

over 过度

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

foo2(x, "y")

because I know that calling foo1() has no side effects, it's just taking some inputs and returning an output. 因为我知道调用foo1()没有副作用,所以它只是接受一些输入并返回输出。 This is a little contrived because you chose assign() but this would apply broadly. 这有点人为,因为您选择了assign()但这将广泛适用。 It's also the reason why complex lists or other types of objects are returned from many R functions, especially those fitting a model. 这也是为什么许多R函数(尤其是适合模型的R函数)返回复杂列表或其他类型的对象的原因。

Don't mention an environment in the assign. 不要在分配中提及环境。

 foo = function(a,b){
  assign(paste(a,b,sep="."),99)
 return(hey.you) # note this is hard coded here...
}

There's nothing called hey.you : 没有什么叫hey.you

> ls()
[1] "foo"

I call foo , which creates a hey.you and returns its value: 我叫foo ,它创建一个hey.you并返回其值:

> foo("hey","you")
[1] 99

But doesn't mess up my environment because it was created in the function's environment: 但是不会弄乱我的环境,因为它是在函数的环境中创建的:

> ls()
[1] "foo"

because that's the default. 因为这是默认设置。

?assign

    pos: where to do the assignment.  By default, assigns into the
          current environment.  See ‘Details’ for other possibilities.

If you HAD to mention it explicitly, and you don't have to, so don't, unless you can give us a real good reason why you have to, then just copy what assign does: 如果您必须明确提及它,而不必这样做,除非您可以给我们一个确实有充分理由的理由,否则只需复制assign的工作即可:

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

Or copy what everyone else has been saying here: 或复制其他人在这里所说的话:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM