代码之家  ›  专栏  ›  技术社区  ›  CL.

如何将Curry()与Vectorize()结合?

  •  5
  • CL.  · 技术社区  · 7 年前

    addAmount <- function(x, amount) {
      stopifnot(length(x) == 1)
      return(x + amount)
    }
    

    它可以用来添加一些 amount x :

    > addAmount(x = 5, amount = 3)
    [1] 8
    > addAmount(x = 2, amount = 3)
    [1] 5
    

    然而 x 长度必须为1:

    > addAmount(x = 7:9, amount = 3)
     Error: length(x) == 1 is not TRUE 
    

    使用 Vectorize x :

    > Vectorize(addAmount)(x = 7:9, amount = 3)
    [1] 10 11 12
    

    到目前为止,一切顺利。

    addAmount 函数转换为“add 3”函数,使用currying:

    add3 <- functional::Curry(addAmount, amount = 3)
    

    x 长度不是1:

    > add3(x = 5)
    [1] 8
    > add3(x = 7:9)
     Error: length(x) == 1 is not TRUE
    

    问题是: add3 无法矢量化:

    > Vectorize(add3)(x = 7:9)
     Error: length(x) == 1 is not TRUE 
    

    矢量化 ,即它的行为就像它根本没有被矢量化一样。

    问题: 我该怎么办?货币化和矢量化如何结合?(还有:出了什么问题?)


    我找到了一个解决方法(灵感来源于 Hadley's add function )使用环境而不是 Curry ,但我正在寻找一种更清洁的解决方案,它不需要这种笨拙的“工厂”功能:

    getAdder <- function(amount) {
      force(amount)
      addAmount <- function(x) {
        stopifnot(length(x) == 1)
        return(x + amount)
      }
      return(addAmount)
    }
    
    add3 <- getAdder(3)
    Vectorize(add3)(x = 7:9)
    [1] 10 11 12
    

    用R 3.4.1和 functional 软件包(版本0.6)。

    1 回复  |  直到 7 年前
        1
  •  2
  •   eipi10    7 年前

    您可以在套用之前进行矢量化:

    add3 <- functional::Curry(Vectorize(addAmount), amount = 3)
    
    add3(1:10)