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

CL.*_*CL. 5 functional-programming r vectorization currying

考虑以下功能:

addAmount <- function(x, amount) {
  stopifnot(length(x) == 1)
  return(x + amount)
}
Run Code Online (Sandbox Code Playgroud)

它可以用于一些新增amountx:

> addAmount(x = 5, amount = 3)
[1] 8
> addAmount(x = 2, amount = 3)
[1] 5
Run Code Online (Sandbox Code Playgroud)

但是,x长度必须为1:

> addAmount(x = 7:9, amount = 3)
 Error: length(x) == 1 is not TRUE 
Run Code Online (Sandbox Code Playgroud)

我故意将此限制添加到示例中.

使用Vectorize,可以传入一个向量x:

> Vectorize(addAmount)(x = 7:9, amount = 3)
[1] 10 11 12
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.

但是,我想addAmount使用currying 将我的函数转换为"add 3"函数:

add3 <- functional::Curry(addAmount, amount = 3)
Run Code Online (Sandbox Code Playgroud)

如果x长度为1,则按预期工作,如果长度不为1,则失败(如预期)x:

> add3(x = 5)
[1] 8
> add3(x = 7:9)
 Error: length(x) == 1 is not TRUE
Run Code Online (Sandbox Code Playgroud)

问题是:add3无法矢量化:

> Vectorize(add3)(x = 7:9)
 Error: length(x) == 1 is not TRUE 
Run Code Online (Sandbox Code Playgroud)

不知何故,curried函数与"兼容" Vectorize,即它表现得好像根本没有矢量化.

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


我找到了一种使用环境而不是使用环境的解决方法(受Hadley add功能的启发)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
Run Code Online (Sandbox Code Playgroud)

使用R 3.4.1和functional软件包(版本0.6)进行测试.

eip*_*i10 2

您可以在柯里化之前进行矢量化:

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

add3(1:10)
Run Code Online (Sandbox Code Playgroud)

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