我刚刚读完R intro 中关于范围界定的<<-内容,并且对这项任务非常好奇。
<<-
该手册显示了一个(非常有趣的)示例<<-,我觉得我理解了。我仍然缺少的是何时有用的上下文。
所以我很想从你那里读到一些例子(或例子的链接),关于什么时候使用<<-可以是有趣/有用的。使用它可能有什么危险(看起来很容易忘记),以及您可能想要分享的任何提示。
<<-与闭包一起维护状态最有用。这是我最近的一篇论文中的一段:
闭包是由另一个函数编写的函数。闭包之所以被称为闭包,是因为它们 包围 了父函数的环境,并且可以访问该函数中的所有变量和参数。这很有用,因为它允许我们有两个级别的参数。一级参数(父级)控制函数的工作方式。另一个级别(孩子)做这项工作。下面的例子展示了如何使用这个想法来生成一系列幂函数。父函数 ( power) 创建子函数 (square和cube),它们实际上完成了艰苦的工作。
power
square
cube
power <- function(exponent) { function(x) x ^ exponent } square <- power(2) square(2) # -> [1] 4 square(4) # -> [1] 16 cube <- power(3) cube(2) # -> [1] 8 cube(4) # -> [1] 64
在两个级别上管理变量的能力还可以通过允许函数修改其父环境中的变量来跨函数调用维护状态。在不同级别管理变量的关键是双箭头赋值运算符 <<-。与通常<-在当前级别上始终有效的单箭头赋值 ( ) 不同,双箭头运算符可以修改父级别中的变量。
<-
这使得可以维护一个计数器来记录函数被调用的次数,如下面的示例所示。每次new_counter运行,它都会创建一个环境,在这个环境中初始化计数器i,然后创建一个新的函数。
new_counter
i
new_counter <- function() { i <- 0 function() { # do something useful, then ... i <<- i + 1 i } }
新函数是一个闭包,它的环境是封闭环境。当闭包counter_one和counter_two运行时,每个都修改其封闭环境中的计数器,然后返回当前计数。
counter_one
counter_two
counter_one <- new_counter() counter_two <- new_counter() counter_one() # -> [1] 1 counter_one() # -> [1] 2 counter_two() # -> [1] 1