我正在考虑在R中实现块作用域的方法。这对于在数据科学笔记本/交互式会话中保持干净的工作空间非常有用。目前我正在使用像这样的IIFE模式
x = names.splitlines()
通过这种方式,我可以创建/更新数据,并在我之后清除临时数据。显然它在潜在地分配给全局方面仍然有副作用,但是对于数据分析而不是我不关心的软件包。
直到IIFE在R中越来越受欢迎我认为有一个特殊的操作员可以做到这一点,但我不太了解R元编程。在我天真的头脑中,以下应该已经足够了
(function(){
temp1 <- ...
temp2 <- ...
temp3 <- ...
data <<- fn(temp1, temp2, temp3)
})()
但是x仍然会被淘汰到我的全球范围。所以
答案 0 :(得分:2)
1)本地首先请注意这是有效的:
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%
,我们可以像这样使用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)。
答案 1 :(得分:1)
local
做你想做的事情(而且IIFE是JavaScript中的一个黑客,可以解决缺少local
功能的问题。)
你的%gets%
代码失败了,因为你误解了如何评估参数:在你的函数中,val
是一个参数。这意味着在呼叫者的范围内进行评估,没有例外。将其包含在local
中仅意味着评估val
的结果包含在本地 - 即在这种情况下无意义。 不意味着表达式是在本地评估的;如果是这种情况,你根本不需要local
,你可以在函数的范围内对它进行评估。
如果您愿意, 可以1>}
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
)
}
作业的一种复杂方式。