使用 R 的元编程来处理函数参数

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

这项工作只是为了好玩,作为进一步学习 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)

r eval metaprogramming rlang
1个回答
0
投票

我有一个不太优雅的解决方案,但我相信有更好的方法来做到这一点。

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