功能环境

时间:2018-03-25 17:48:03

标签: r function

我正在阅读Hands-on Programing with R,他在一个例子中创建了以下函数:

setup <- function(deck){
      DECK <- deck

      DEAL <- function(){
            card <- deck[1,]
            assign("deck",deck[-1,],envir = parent.env(environment()))
            card
      }

      SHUFFLE <- function(){
              random <- sample(1:52,52)
              assign("deck",DECK[random,],envir = parent.env(environment()))
      }
      list(deal=DEAL, shuffle=SHUFFLE)
}

cards <- setup(deck)
deal <- cards$deal
shuffle <- cards$shuffle

甲板是here

当我第一次呼叫deal时,显示的环境为<environment: 0x9eea314>。然后我开始处理函数deal(),我发现如果再次调用setup(deck),交易功能将被重置。我这样做了,deal的环境变为<environment: 0xad77a60>,但令我惊讶的是,当我处理deal()时,它已经停止了。我打电话给deal,我看到事实上环境并没有改变。

发生了什么事?当我第一次设置交易功能时,无论我调用setup(deck)多少次它都不会改变,或者我在其他环境中创建其他函数处理,而范围规则无法达到?

1 个答案:

答案 0 :(得分:3)

我认为问题在于您想要查看的“牌组”位于cards - 对象内。在shuffle()之后,我们可以看到此行为:

> deal()
   face  suit value
17  ten clubs    10
> str(deck)
'data.frame':   52 obs. of  3 variables:
 $ face : Factor w/ 13 levels "ace","eight",..: 6 8 5 11 7 2 9 10 3 4 ...
 $ suit : Factor w/ 4 levels "clubs","diamonds",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ value: int  13 12 11 10 9 8 7 6 5 4 ...

所以我确实看到了你的困惑。我和你一样,期待在牌组中看到51张牌,我期待随机排列牌值和套牌(我们也看不到),但让我们继续......

> deal()
    face     suit value
37 three diamonds     3
> deal()
   face  suit value
23 four clubs     4
> str(cards)

现在让我们尝试找到deckshuffle函数操纵的“真实”deal - 对象,它显然与{{1}不同在deck中保持不变的对象。 R函数实际上是闭包,它是代码和封闭环境的组合。考虑到这一点,让我们检查globalenv()

cards

现在检查> str(cards) List of 2 $ deal :function () ..- attr(*, "srcref")=Class 'srcref' atomic [1:8] 4 15 8 7 15 7 4 8 .. .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x7f84081d3780> $ shuffle:function () ..- attr(*, "srcref")=Class 'srcref' atomic [1:8] 10 18 13 7 18 7 10 13 .. .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x7f84081d3780> 内第一个函数的 environment

cards

现在看一下那个环境中“deck”的价值:

> ls(env=environment(cards[[1]]))
[1] "DEAL"    "deck"    "DECK"    "SHUFFLE"

所以我认为我们已经找到了我们应该关注的实际“甲板”对象(因为它具有正确的数字和随机排序),并且它不是{{1中的那个仍然(未改变)的那个}}。此外,这两个功能的环境是共享的:

str(environment(cards[[1]])$deck)
'data.frame':   49 obs. of  3 variables:
 $ face : Factor w/ 13 levels "ace","eight",..: 4 1 13 7 11 13 8 2 2 3 ...
 $ suit : Factor w/ 4 levels "clubs","diamonds",..: 4 1 4 1 3 3 4 3 4 1 ...
 $ value: int  4 1 2 9 10 2 12 8 8 5 ...

...但是,如果在游戏过程中意外执行了globalenv(),我认为游戏“语义”可能存在问题:

 environment(cards[[2]])
#<environment: 0x7f84081702a8>
 environment(cards[[1]])
#<environment: 0x7f84081702a8>