函数被证实地称为“闭包(closure)”,R中的函数有三个基本属性,前两者是构成函数,后者是这个函数的生存环境。
#实例,y z 是numeric
f <- function(x, y = 1, z = 2) {
paste(x, y, z)
}
f(0)
## [1] "0 1 2"
formals(f) <- alist(x =, y = "mm", z = "gg")
f("ss")
## [1] "ss mm gg"
#打印函数体
body(f)
## {
## paste(x, y, z)
## }
在计算机程序设计中,变量是名字(name)与实体(entity)的绑定(binding)。一段程序代码中所用到的名字并不总是有效(或者说:可用的),而限定这个变量名字具有可用性的代码范围就是这个名字的作用域。
w <- 1
func <- function(y){
a <- 2
h <- function(){
b <- 1
z <- b * (w + y) + b
h_scoping_values <- list("ss" = b, "xx" = y, "kk" = z, ls())
h_scoping_values
}
func_scoping_values <- list("mm" = a, "gg" = h, "jj" = ls())
func_scoping_values
}
globalenv_values <- ls()
#作用域范围:h < func < globalenv
此例中,R:函数变量寻值过程:首先在本函数内部,然后到上一层env,可以是f或者env,直至globalenv,最后是load的其他的package。
print(globalenv_values) #全局变量中有func、w
## [1] "f" "func" "w"
func(3) #func函数值,有变量a h y
## $mm
## [1] 2
##
## $gg
## function ()
## {
## b <- 1
## z <- b * (w + y) + b
## h_scoping_values <- list(ss = b, xx = y, kk = z, ls())
## h_scoping_values
## }
## <environment: 0x000000001af3a350>
##
## $jj
## [1] "a" "h" "y"
func(3)[["gg"]]() #h()函数中有变量"b"、"z"
## $ss
## [1] 1
##
## $xx
## [1] 3
##
## $kk
## [1] 5
##
## [[4]]
## [1] "b" "z"
y <- 10
func1 <- function(x){
y <- 2
y^ 2 + func2(x) + func3(x)
}
func2 <- function(x){
x*y
}
#func1(3) #Error in func3(x) : could not find function "func3"
y <- 10
func1 <- function(x){
y <- 2
y^ 2 + func2(x) + func3(x)
}
func2 <- function(x){
x*y
}
# 在调用func3之前,必须有func3的定义
func3 <- function(x){
x+y
}
func1(3)
## [1] 47
实例1:
a <- function(x){
e <- new.env()
e$x <- 1
c <- b(x)
return(c(c, e$y, e$z))
}
b <- function(x){
x <- e$x + x
e$y <- x + 1
e$z <<- x + 2
return(x)
}
e <- new.env()
e$x <- 2
a(3)
## [1] 5
思路分析图: 实例2:
rm(list = ls()) #清除所有变量
a <- function(x){
e <- new.env()
e$x <- 1
b <- function(x){
x <- e$x + x
e$y <- x + 1
e$z <<- x + 2 # 将z变成全局变量
return(x)
}
c <- b(x)
return(c(c, e$y, e$z))
}
e <- new.env()
e$x <- 2
a(3)
## [1] 4 5 6
思路分析图:
ls() #打印全局变量
## [1] "a" "e"
a <- function(x){
e <- new.env()
e$x <- 1
b <- function(x){
x <- e$x + x
e$y <- x + 1
e$z <<- x + 2 # 将z变成全局变量
return(x)
}
c <- b(x)
ls() #打印a函数的所有变量空间 #"b" "c" "e" "x"
}
e <- new.env()
e$x <- 2
ls(envir = e) #"x"
## [1] "x"
a(2)
## [1] "b" "c" "e" "x"
a <- function(x){
e <- new.env()
e$x <- 1
b <- function(x){
x <- e$x + x
e$y <- x + 1
e$z <<- x + 8 # 将z变成全局变量
}
c <- b(x)
ls(envir = e) #"x" "y" "z"
}
e<- new.env()
e$x <- 2
a(2)
## [1] "x" "y" "z"
a <- function(x){
e <- new.env()
e$x <- 1
b <- function(x){
x <- e$x + x
e$y <- x + 1
e$z <<- x + 2 # 将z变成全局变量
ls(envir = e) #"x" "y" "z"
}
c <- b(x)
c#打印b函数的所有变量空间
}
e <- new.env()
e$x <- 2
a(2)
## [1] "x" "y" "z"
情形一:函数a调用函数b中的局部变量
rm(list=ls())
func1<- function(x){
a <- 3
a*x + 3
}
func2 <- function(x){
a*x
}
b <- func1(2)
#func2(b) #Error in func2(func1(2)) : object 'a' not found
情形二:函数a调用函数b中全局变量,但是函数b没有环境
rm(list=ls())
func1<- function(x){
a <<- 3
a*x + 3
}
func2 <- function(x){
a*x
}
#func2(func1(2)) #Error in func2(func1(2)) : object 'a' not found
情形三:函数a调用函数b中全局变量,函数b环境在函数a调用过程中创建了环境。
rm(list=ls())
func1<- function(x){
a <<- 3
a*x + 3
}
func2 <- function(x){
a*x
}
b <- func1(2)
func2(b)
## [1] 27
## 结果为27
情形四:工作空间是不是最顶层环境?
rm(list=ls())
func1<- function(x){
a <<- 3
a*x + 3 #9
}
func2 <- function(x){
a*x
}
a <- 1
func2(func1(2)) #func1(2) = 9,此时先去工作空间查找到a=1,而不是取全局变量a=3
## [1] 9
## 结果为9
通过分析:全局变量a需要在一个特定的环境中,最后代码块中,a存在func1的环境中,当func2中需要a时,先func2函数中找a再从创建func2函数的环境找,最后在全局变量找,全局变量应该是最顶层。