[英]How to achieve block scoping in R?
我正在考虑在R中实现块作用域的方法。这对于在数据科学笔记本/交互式会话中保持干净的工作空间非常有用。 目前,我正在使用这样的IIFE模式
(function(){
temp1 <- ...
temp2 <- ...
temp3 <- ...
data <<- fn(temp1, temp2, temp3)
})()
这样,我可以创建/更新数据,并让临时文件在我之后被清理。 显然,它在潜在地分配给全局方面仍然有副作用,但是对于数据分析而不是我不关心的软件包。
直到IIFE在RI中变得更流行之前,为此才想到有一个特殊的运算符会很巧妙,但是我对R元编程的了解还不够。 在我幼稚的头脑中,以下内容就足够了
`%gets%` <- function(x, val) {
val <- local(val)
assign(deparse(substitute(x)), val, envir = parent.frame())
}
x1 %gets% {
x = 10;
x + 5
}
但是x仍然被丢弃到我的全局范围内。 所以
1)local首先注意,这有效:
if (exists("x")) rm(x) # just for reproducibility. Don't need this normally.
x1 <- local({ x <- 10; x + 5})
x1
## [1] 15
x
## Error: object 'x' not found
2)%gets%要实现%gets%
我们可以使用如下所示的substitute
:
`%gets%` <- function(.x, .value) {
assign(deparse(substitute(.x)), eval.parent(substitute(local(.value))), parent.frame())
}
x1 %gets% {
x = 10;
x + 5
}
x1
## [1] 15
x
## Error: object 'x' not found
2a):=我们可以通过定义:=来使它变得更好:
`:=` <- `%gets%`
# test
x1 := { x <- 10; x + 5}
x1
## [1] 15
x
## Error: object 'x' not found
3)管道也可以使用管道来避免整体。 在此,管道完成后x
和y
不会持续存在。
library(magrittr)
list(x = 6) %$% { y <- 1; x + y + 5 }
## [1] 12
x
## Error: object 'x' not found
y
## Error: object 'y' not found
或如果我们没有什么可以通过的:
x1 <- list() %>% { x <- 10; x + 5 }
x1
## [1] 15
x
## Error: object 'x' not found
或者我们可以使用0保存击键:
x1 <- 0 %>% { x <- 10; x + 5 }
更新已修订(2)以简化和纠正它。 还添加了(2a)和(3)。
local
可以满足您的要求 (并且IIFE是JavaScript的一种变种,可以解决缺乏类似于local
的功能的问题)。
您的%gets%
代码失败,因为您误解了如何评估参数:在函数中, val
是一个参数。 这意味着它将在调用方的范围内进行评估 ,没有例外。 将其包装在local
只是意味着将val
的评估结果包装在local中,即在这种情况下没有意义。 这并不意味着该表达式为本地计算; 如果是这种情况,则完全不需要local
,可以在函数的作用域中对其进行评估。
您可以根据需要使用eval
来做到这一点:
`%gets%` = function (x, expr) {
assign(
as.character(substitute(x)),
eval(substitute(expr)),
parent.frame()
)
}
…但这不是很有用,因为它无法访问调用者作用域的变量; 相反,您必须在注入调用者范围的范围内对其进行评估,以便您拥有一个“干净”的环境,但仍可以访问现有变量:
`%gets%` = function (x, expr) {
parent = parent.frame()
assign(
as.character(substitute(x)),
eval.parent(substitute(eval(quote(expr), new.env(parent = parent)))),
parent
)
}
…但这本质上只是重新定义local
分配的一种复杂方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.