如何在R中实现块范围?

时间:2018-05-17 04:55:23

标签: r

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

x = names.splitlines()

通过这种方式,我可以创建/更新数据,并在我之后清除临时数据。显然它在潜在地分配给全局方面仍然有副作用,但是对于数据分析而不是我不关心的软件包。

直到IIFE在R中越来越受欢迎我认为有一个特殊的操作员可以做到这一点,但我不太了解R元编程。在我天真的头脑中,以下应该已经足够了

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

data <<- fn(temp1, temp2, temp3)
})()

但是x仍然会被淘汰到我的全球范围。所以

  1. 这是模拟块范围的合理实现吗?
  2. 如果是这样,我怎样才能阻止我的x逃逸到外部范围?

2 个答案:

答案 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)管道也可以使用管道来避免全局变形。管道完成后,xy不会保留。

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,你可以在函数的范围内对它进行评估。

如果您愿意, 可以}

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 ) } 作业的一种复杂方式。