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

时间:2018-12-29 21:49:41

标签: r function functional-programming namespaces ellipsis

背景

我有一个有趣的功能,可以使用<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>比较列表中的向量。当我使用all.equal时,我想通过省略号传递相关的all.equal参数。无需将任何内容传递给all.equal,该函数即可按需工作。

功能目标

  • 该函数旨在提供适用于任意数量矢量的all.equal调用的修改版本
  • 每个向量可以具有任意数量的元素;但是,如果所有向量的长度都不相等,则该函数将返回false。
  • 该函数应该能够利用all.equal中可用的参数。例如,如果提供了具有正确值的all.equal自变量,则向量c(1.1, 2)c(1, 2)c(1.3, 2)将被视为相等。 问题与该功能有关。

示例

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

tolerance

问题/预期结果

在以下向量列表上用 compare_multiple_vectors(x = lapply( X = vector(mode = "list", length = 1e3), FUN = function(...) { c(1, 2, 3) } )) # [1] TRUE 调用的

all.equal将返回预期的tolerance = 1

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)
        }
    }
    

1 个答案:

答案 0 :(得分:3)

我认为只需要一点改变:

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)
    }
}

Redem 的参数 f 似乎具有签名,如 function(x,y)。因此, Reduce 将忽略 f 中的 ... 。如果删除 f 的省略号,则会从外层空间引用 ... ,并且将得到所需的正确结果。