延迟绑定(lazy binding)和动态绑定(active binding)
R语言中,除了一般的变量赋值,还用两种特殊的赋值方式。一种是延迟绑定(lazy binding),还有一种是动态绑定(active binding)。
延迟绑定首次访问变量的时候,进行值的计算(evaluation),而动态绑定时每次访问时,都重新进行值的计算。
实现方式
Base R
延迟绑定
采用delayedAssign(),举个delayedAssign帮助自带的栗子:
delayedAssign("x", {
for(i in 1:3)
cat("yippee!\n")
10
})
x^2 #- yippee
x^2 #- simple number
执行的结果是:
> delayedAssign("x", {
+ for(i in 1:3)
+ cat("yippee!\n")
+ 10
+ })
> x^2 #- yippee
yippee!
yippee!
yippee!
[1] 100
> x^2 #- simple number
[1] 100
动态绑定
采用makeActiveBinding(sym, fun, env),举个makeActiveBinding帮助自带的栗子:
# active bindings
f <- local( {
x <- 1
function(v) {
if (missing(v))
cat("get\n")
else {
cat("set\n")
x <<- v
}
x
}
})
makeActiveBinding("fred", f, .GlobalEnv) # f 是之前返回的闭包函数
bindingIsActive("fred", .GlobalEnv)
fred
fred <- 2
fred
执行的结果是:
> f <- local( {
+ x <- 1
+ function(v) {
+ if (missing(v))
+ cat("get\n")
+ else {
+ cat("set\n")
+ x <<- v
+ }
+ x
+ }
+ })
> makeActiveBinding("fred", f, .GlobalEnv)
> bindingIsActive("fred", .GlobalEnv)
[1] TRUE
> fred
get
[1] 1
> fred <- 2
set
get
> fred
get
[1] 2
rlang package
package rlang也提供函数
env_bind_lazy()
env_bind_active()
完成延迟绑定和动态绑定。使用之前先安装rlang
install.packages("rlang")
library(rlang)
延迟绑定
修改上述的例子:
env_bind_lazy(current_env(), y = {
for(i in 1:3)
cat("yippee!\n")
10
})
y^2 #- yippee
y^2 #- simple number
结果:
> env_bind_lazy(current_env(), y = {
+ for(i in 1:3)
+ cat("yippee!\n")
+ 10
+ })
> y^2 #- yippee
yippee!
yippee!
yippee!
[1] 100
> y^2 #- simple number
[1] 100
动态绑定
修改上述的例子:
# active bindings
ff <- local( {
x <- 1
function(v) {
if (missing(v))
cat("get\n")
else {
cat("set\n")
x <<- v
}
x
}
})
env_bind_active(current_env(), fred = ff)
bindingIsActive("fred", .GlobalEnv)
fred
fred <- 2
fred
执行结果:
> # active bindings
> ff <- local( {
+ x <- 1
+ function(v) {
+ if (missing(v))
+ cat("get\n")
+ else {
+ cat("set\n")
+ x <<- v
+ }
+ x
+ }
+ })
> env_bind_active(current_env(), fred = ff)
> bindingIsActive("fred", .GlobalEnv)
[1] TRUE
> fred
get
[1] 1
> fred <- 2
set
> fred
get
[1] 2