如何在R中实现块范围?

如何在R中实现块范围?,r,R,我正在考虑在R中实现块范围的方法。这对于在数据科学笔记本/交互式会话中保持干净的工作空间是很好的。目前我正在使用这样的模式 (function(){ temp1 <- ... temp2 <- ... temp3 <- ... data <<- fn(temp1, temp2, temp3) })() (函数(){ temp11)本地首先请注意,这是有效的: if (exists("x")) rm(x) # just for reproducibility.

我正在考虑在R中实现块范围的方法。这对于在数据科学笔记本/交互式会话中保持干净的工作空间是很好的。目前我正在使用这样的模式

(function(){
temp1 <- ...
temp2 <- ...
temp3 <- ...

data <<- fn(temp1, temp2, temp3)
})()
(函数(){
temp11)本地首先请注意,这是有效的:

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
2a):=我们可以通过这样定义:=使这一点变得更好:

`%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
`:=` <- `%gets%`

# test
x1 := { x <- 10; x + 5}

x1
## [1] 15

x
## Error: object 'x' not found
或者如果我们没有什么可通过的:

x1 <- list() %>% { x <- 10; x + 5 }

x1
## [1] 15

x
## Error: object 'x' not found

x1%{x
local
做你想做的事
(iLife是JavaScript中的一个黑客,用来解决缺少类似于
local
的功能)

您的
%get%
代码失败,因为您误解了参数的求值方式:在函数中,
val
是一个参数。这意味着它在调用方的作用域中求值,没有例外。将其包装在
local
中只意味着将求值的结果包装在
val
中局部-即在本例中无意义。这并不意味着表达式是局部求值的;如果是这种情况,则根本不需要
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
赋值的一种复杂方式。

你的意思是喜欢吗?我的代码中有
local
,它不能足够快地捕捉表达式,x会逃逸到外部范围,如果你运行我的示例代码,你就会看到。我猜在
val中,很少有人会立即知道IIFE=Invoked函数表达式,您也可以引用,并简洁地解释它与R实现环境的比较,例如,第3个和第4个参数具体说明IIFE与
assign(…,new.env(parent=baseenv())…
globalenv()
emptyenv()
等等?和@shians关于
local
你错了。它完全符合你的要求。如果JavaScript有
local
,它就不需要iLife。
如果(存在(“x”))rm(x)
-我不确定这在这里起什么作用。我通常也不喜欢将环境视为可变工作区。尽可能将其视为不可变的(即:不要重新绑定名称,也不要删除它们)。这只是为了测试的再现性。否则就不需要了。当我们使用显示的后续代码时,我们不需要该语句。注释2a已添加。
局部
的+1,这是最具R-onic的方法。(听起来不像“pythonic”那么流畅,但是…有更好的说法吗?也许不是最好的。。。“是不是R-onic”听起来像是Alanis Morisette,“更R-onic”听起来像是白痴……)
x1 <- 0 %>% { x <- 10; x + 5 }
`%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
    )
}