3

我无法理解如何将函数内的值绑定到函数外的环境。下面显示了一个基本示例,我似乎无法解决函数的最后一部分:

number <- data.frame()

how_many_fruits <- function() {

    answer <- as.integer(readline(prompt="How Many?: "))
    globalenv()$number <- rbind(globalenv()$number, answer)

}

本质上,我希望number在开始时调用一个空数据框,并且每次how_many_fruits()运行时,我都希望将输入附加到number数据框的底部。

4

2 回答 2

7

您可以使用<<-运算符:

number <- data.frame()
how_many_fruits <- function() {

  answer <- as.integer(readline(prompt="How Many?: "))  
  number <<- rbind(number, answer)

}

但是,我想知道您使用该程序的目标是什么。函数不应该像你那样使用全局环境中的变量。如果有人想使用该函数,但调用变量num而不是 ,会发生什么number?该功能在这种情况下不起作用。因此,我建议您改为执行以下操作:

how_many_fruits <- function(num) {

  answer <- as.integer(readline(prompt="How Many?: "))
  new_num <- rbind(num, answer)

  return (new_num)
}

number <- data.frame()
number <- how_many_fruits(number)

这就是一个函数应该如何工作的:它接受输入(这里称为num)并返回一个输出(这里称为new_num)。请注意,函数内部的输入和输出名称不必与函数外部使用的变量名称相同。当您调用 时how_many_fruits(number), 的内容number存储在num其中,该功能仅适用于后者。当你这样做时number <- how_many_fruits(number),作为结果返回的任何内容how_many_fruits(number)都存储在number.

于 2016-05-21T08:04:17.173 回答
3

直接从函数内部修改全局环境不是一个好主意。通常最好只返回一个值并让用户将其附加到需要的地方。(正如 Stibu 解释的那样)。

但是,您还可以使用嵌套环境,例如以下对官方 R 语言定义示例的修改:

fruitscollector <- function(){
  fruitslist <- NULL
  function(){
    answer <- as.integer(readline(prompt="How Many?: "))
    fruitslist <<- c(fruitslist, answer)
    fruitslist
  }
}

所以当你第一次初始化一个“fruitscollector”时,它只返回一个可以收集值的函数。

foo <- fruitscollector()

现在每次使用时foo,都会向集合添加一个值(并返回整个集合):

foo()
foo()
# etc

fruitslist存储在 的父环境中 foo,因此不会在您可能意外删除的全局环境中。

编辑

一个更一般的想法是创建一个对象(有点类似于 OOP 中所谓的“对象”),其中函数作为方法,例如

collector <- function(){
  stack <- NULL
  list(
    add = function(x) stack<<-c(stack, x),
    get = function() stack,
    empty = function() stack <<- NULL
  )
}

现在add方法将添加到堆栈中,get方法将返回整个堆栈,empty方法将清空它。

foo <- collector()  # initialize
foo$get()  # NULL
foo$add(1)  # add 1 to the stack
foo$get()  # 1
foo$add(3)  # add 3 to the stack
foo$get()  # 1 3
foo$add(1:5) # etc...
于 2016-05-21T08:46:02.620 回答