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

时间:2017-07-11 15:02:46

标签: r functional-programming vectorization currying

考虑以下功能:

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功能转换为&#34;添加3&#34;功能,使用currying:

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

如果x的长度为1且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 

不知何故,咖喱功能不兼容&#34;使用Vectorize,即它的行为就像它根本没有被矢量化一样。

问题:我该怎么办?如何组合currying和矢量化? (并且:出了什么问题?)

我找到了一种使用环境而不是Curry的解决方法(受到Hadley's add function的启发),但我正在寻找一种不需要这种笨拙的清洁解决方案#34;工厂&#34;功能:

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 个答案:

答案 0 :(得分:2)

你可以在currying之前进行矢量化:

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

add3(1:10)
  

[1] 4 5 6 7 8 9 10 11 12 13