传递要在 Reduce 中的函数调用中评估的省略号参数

Passing elipsis argument to be evaluated within function call within Reduce

背景

我有一个有趣的函数,可以使用 all.equal 比较列表中的向量。当我使用 all.equal 时,我想通过省略号传递相关的 all.equal 参数。无需向 all.equal 传递任何内容,该函数就可以正常工作。

功能目标

例子

比较 1,000 个向量,每个向量由三个整数组成。

    compare_multiple_vectors(x = lapply(
              X = vector(mode = "list", length = 1e3),
              FUN = function(...) {
                  c(1, 2, 3)
              }
          ))

    # [1] TRUE

问题/期望的结果

all.equal 在以下向量列表中使用 tolerance = 1 调用将 return 预期 TRUE

all.equal(c(1,2), c(1,1), tolerance = 1)
# [1] TRUE

tolerance = 1 参数无法过滤到 Reduce 内部。

compare_multiple_vectors(x = list(c(1,2), c(1,1)), tolerance = 1)
# [1] FALSE

想要的结果应该是TRUE.


代码

#' @title Compare Values of Multiple Vectors
#'
#' @description The function compares values across multiple vectors using
#'   \code{\link[base]{all.equal}}.
#'
#' @param x Alist of vectors to compare
#' @param ... as in  \code{\link[base]{all.equal}}
#'
#' @return A logical
#'
#' @export
#'
#' @importFrom checkmate assert_atomic_vector
#'
#' @examples
#' # Returns TRUE
#' compare_multiple_vectors(c(1,1,1), c(1,1,1))
#' # Returns FALSE
#' compare_multiple_vectors(c(1,1,1), c(1,1,1), c(1,2,1))
#' # Returns FALSE
#' compare_multiple_vectors(c(1,2,3), c(3,2,1))
compare_multiple_vectors <- function(x, ...) {
    # Check if all elements of x are atomic vectors
    Vectorize(FUN = checkmate::assert_atomic_vector,
              vectorize.args = "x")(x)

    # Compare list elements
    Reduce(
        f = function(a, b, ...) {
            if (isTRUE(all.equal(target = a, current = b, ...))) {
                a
            } else {
                FALSE
            }
        },
        x = x
    ) -> res_red

    # Return results
    if (isFALSE(res_red)) {
        return(FALSE)
    } else {
        return(TRUE)
    }
}

备注

我认为只需要一点点改变:

compare_multiple_vectors <- function(x, ...) {
    # Check if all elements of x are atomic vectors
    Vectorize(FUN = checkmate::assert_atomic_vector,
              vectorize.args = "x")(x)

    # Compare list elements
    Reduce(
        f = function(a, b) {  # <===================== Remove *...*

            if (isTRUE(all.equal(target = a, current = b, ...))) {
                a
            } else {
                FALSE
            }
        },
        x = x
    ) -> res_red

    # Return results
    if (isFALSE(res_red)) {
        return(FALSE)
    } else {
        return(TRUE)
    }
}

Reduce 的参数 f 似乎有一个 signature函数(x,y)。所以 Reduce 将忽略 ...f 中。如果删除 f 的省略号,... 将从外部 space 引用,并将得到您想要的正确结果。