簡體   English   中英

您是否必須在R中定義函數的環境?

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

您是否必須在R中顯式定義自定義函數的環境,還是在創建函數時自動“創建”(定義?)?

我想知道是否創建函數會自動在所述函數內創建環境,或者是否需要顯式創建環境。 如果前者是正確的(即,環境是自動創建的),我如何顯式引用它?

我必須首先為上述函數創建一個新環境(即,通過使用new.env分配一個新環境)還是可以簡單地使用其他語法(例如“ current.env()類的東西current.env() ”?

我可以使用的唯一簡單示例就是在函數內部assign函數。

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

當前環境由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函數(尤其是適合模型的R函數)返回復雜列表或其他類型的對象的原因。

不要在分配中提及環境。

 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.

如果您必須明確提及它,而不必這樣做,除非您可以給我們一個確實有充分理由的理由,否則只需復制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"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM