这项工作只是为了好玩,作为进一步学习 R 元编程的一种方式。我正在尝试实现列表推导式,就像您在 Haskell 或 Python 中看到的那样。我只是不确定如何修复该过程的一小部分。我正在遵循 %>% 的示例实现,并进行一些更改。这是代码:
library(rlang)
`%c|%` <- function(lhs, rhs){
lhs <- (substitute(lhs))
rhs <- (substitute(rhs))
if (rhs[[1L]] == ".") rhs[[1]] = quote(list)
e <- expr(purrr::pmap(!!rhs, \(x, y) !!lhs))
eval(e, envir = parent.frame())
}
c(x, y) %c|% .(x = 1:2, y = 10:11)
# returns as expected
[[1]]
[1] 1 10
[[2]]
[1] 2 11
您可能会注意到,问题是我必须自己在
\(x, y)
中进行硬编码。我不知道如何以类似于设置的其余部分的方式创建它。另一个问题是,即使提供了无关的变量,我也希望运算符能够工作。例如:
> c(x, y) %c|% .(x = 1:2, y = 10:11, z = letters[1:2])
Error in `purrr::pmap()`:
ℹ In index: 1.
Caused by error in `.f()`:
! unused argument (z = .l[[3]][[i]])
我一直在阅读 Advanced R 的元编程章节,但似乎找不到解决方案。 我想将硬编码的
\(x, y)
替换为根据右侧命名参数创建的内容。因此,在上面的示例中,我需要创建 \(x, y, z)
或 function(x, y, z)
。
我有一个不太优雅的解决方案,但我相信有更好的方法来做到这一点。
library(rlang)
`%c|%` <- function(lhs, rhs){
lhs <- (substitute(lhs))
rhs <- (substitute(rhs))
if (rhs[[1L]] == ".") rhs[[1]] = quote(list)
args <- (paste(names(as.list(rhs[-1L])), collapse = ","))
e <- expr(purrr::pmap(!!rhs, \(...) {
args <- list(...)
for(i in 1:length(args)) {
assign(x = names(args)[i], value = args[[i]])
}
!!lhs
}
))
eval(e, envir = parent.frame())
}