我有一个全局变量x
,并希望构建一个函数f
,它在创建函数时返回x
的值。例如:
x <- 5
f <- function() return(x)
f()
> 5
x <- 10
f()
> 10 # Should return 5
我想要一个总是返回5
的函数(或函数创建时x
的值),而不使用另一个全局变量。这可能吗?
答案 0 :(得分:3)
使用body
的另一个选项:
f<-`body<-`(function() {},value=x)
示例:
x<-10
f<-`body<-`(function() {},value=x)
f()
#[1] 10
x<-100
f()
#[1] 10
挖掘body
的源代码,这里使用as.function
是一个更加清晰的解决方案:
f<-as.function(list(x))
答案 1 :(得分:2)
仅使用全局变量是不可能的。定义函数时,在调用函数之前,函数体中的所有变量都不会被实际计算。你想要的似乎是在创建时保持价值的闭包。而是编写一个返回函数的函数
x <- 5
getfun <- function() {z<-x; function() return(z)}
f <- getfun()
x<- 10
g <- getfun()
f()
# [1] 5
g()
# [1] 10
或者甚至更好,不要隐含地使用全局变量。创建一个函数,该函数接受一组特定参数并返回一个新函数
returnVal <- function(x) {force(x); function() return(x)}
f<-returnVal(5)
g<-returnVal(10)
f()
# [1] 5
g()
# [1] 10
答案 2 :(得分:2)
1)这会在第一次调用f时保存x的值,然后使用x的值,即使下次调用f时x已被更改。在本地环境中创建f并在该环境中放置x。如果x以前没有,那么现在就是。如果它以前在那里那么将检索并放回x。结果是始终使用遇到的第一个x。
f <- local(function() {
p <- parent.env(environment())
p$x <- x
x
})
x <- 5
f()
## [1] 5
x <- 10
f()
## [1] 5
2)在评论中@Konrad和@Frank提出了以下变体,我们从f中删除了赋值并将其放在本地。
从功能的用户的角度来看,存在一个区别。这会在定义函数时实例化x的值,而(1)在第一次调用函数时实例化x,如果要分离定义和实例化,这可能是一个优势。
x <- 5
f <- local({ x <- x; function() x })
f()
## [1] 5
x <- 10
f()
## [1] 5
3)我们还可以考虑将函数与实例化完全分离。这也可以通过再次调用e $ init()随时重新初始化。
e <- local({
init <- function() {
p <- parent.env(environment())
p$x <- x
}
run = function() x
environment()
})
x <- 5
e$init()
e$run()
## [1] 5
x <- 10
e$run()
## [1] 5
4)(3)可以使用各种面向对象的框架实现,例如Reference Classes,proto或R6。在原型中它会是这样的:
library(proto)
p <- proto(init = function(.) .$x <- x, run = function(.) x)
x <- 5
p$init()
p$run()
## [1] 5
x <- 10
p$run()
## [1] 5