R 的管道分配函数——不分配任何东西

问题描述 投票:0回答:2

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

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

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

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

退货:

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

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

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

r function pipe assign magrittr
2个回答
3
投票

问题中的代码确实分配了它,但分配是针对运行函数中存在的环境(有时称为框架),因此当该函数退出时它会丢失。试试这个定义。请注意,重要的是 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 个,而不是在管道创建的任何临时环境中。我们可以交替使用 e <- .GlobalEnv if we wanted thirteen to be injected into the global environment.

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

更新

扩展和修复错误。


2
投票

默认情况下

assign
在其当前范围内分配值,即在本例中的函数内。在
envir = parent.frame()
.
中指定
assign

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
© www.soinside.com 2019 - 2024. All rights reserved.