R的可管道分配功能——不分配任何东西

Pipeable assign function for R -- does not assign anything

我一直在尝试制作一个可管道化的 assign() 函数,以便在循环中与 paste0() 结合使用。

但是我无法让它实际分配任何东西,例如

assignp <- function(value, x) {
  
assign(x, value)
  
} 

assignp(13, "thirteen")
print(thirteen)

returns:

Error in print(thirteen) : object 'thirteen' not found

没有错误信息,只是没有给指定的变量名赋值。

谁能告诉我我做错了什么?

默认情况下 assign 在其当前范围内赋值,即在本例中的函数内。在 assign.

中指定 envir = parent.frame()
assignp <- function(value, x) {
  assign(x, value, envir = parent.frame())
  #You can also use .GlobalEnv to assign to global environment directly.
  #assign(x, value, envir = .GlobalEnv)
} 

assignp(13, "thirteen")
thirteen

#[1] 13

问题中的代码确实分配了它,但分配给了存在于 运行 函数中的环境(有时称为框架),因此当该函数退出时它会丢失。试试这个定义。请注意,重要的是 envir 是解决一般情况的参数。

assignp <- function(value, x, envir = parent.frame()) {
  assign(x, value, envir)
} 

下面我们讨论使用 %>% 在全局环境中使用它,在函数中使用 %>% 以及在这两种情况下使用 |> 。 magrittr 还定义了一个顺序管道,但没有为它定义一个运算符,我们展示了如何使用它来进一步简化它。我们还表明 assignp 并不是真正需要的,我们可以只使用 assign。

使用 %>%

请注意,如果我们遗漏了 .GlobalEnv,那么 13 将被注入到管道创建的临时环境中,因此在管道的下一段将无法访问它,并且以下将给出错误。

library(magrittr)

if (exists("thirteen")) rm(thirteen)

13 %>% assignp("thirteen", .GlobalEnv) %>% { . + thirteen }
## [1] 26

thirteen
## 13

使用 %>%

从函数调用

通过传递当前环境,在其中定义了 13 个,而不是在管道创建的任何临时环境中。如果我们想将 13 注入到全局环境中,我们可以交替使用 e <- .GlobalEnv。

f <- function(x)  {
  e <- environment()
  x %>% 
  assignp("thirteen", e) %>% 
  { . + thirteen }
}

if (exists("thirteen")) rm(thirteen)
f(13)
## [1] 26

exists("thirteen")
## [1] FALSE

使用 |>

|> 不创建环境,所以这有效。

if (exists("thirteen")) rm(thirteen)
13 |> assignp("thirteen") |> (\(x) x + thirteen)()
## [1] 26

thirteen
## 13



g <- function(x) x |> assignp("thirteen") |> (\(x) x + thirteen)()

if (exists("thirteen")) rm(thirteen)
g(13)
## [1] 26

exists("thirteen")
## [1] FALSE

仅使用赋值

实际上我们根本不需要assignp。这些都有效:

if (exists("thirteen")) rm(thirteen)
13 %>% assign("thirteen", ., .GlobalEnv) %>% { . + thirteen }

f2 <- function(x)  {
  e <- environment()
  x %>% 
  assign("thirteen", ., e) %>% 
  { . + thirteen }
}
if (exists("thirteen")) rm(thirteen)
f2(13)

g2 <- function(x) x |> assign(x = "thirteen") |> (\(x) x + thirteen)()
if (exists("thirteen")) rm(thirteen)
g2(13)

magrittr 顺序管道

magrittr 定义了一个顺序管道,但目前没有它的运算符;但是,我们可以很容易地定义一个。

`%s>%` <- pipe_eager_lexical
f3 <- function(x) x %s>% assign("thirteen", .) %>% { . + thirteen }

if (exists("thirteen")) rm(thirteen)
f3(13)
## [1] 26

更新

扩展并修复了错误。