【发布时间】:2017-12-15 17:34:18
【问题描述】:
考虑以下函数:
addAmount <- function(x, amount) {
stopifnot(length(x) == 1)
return(x + amount)
}
可以用来给x添加一些amount:
> 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 函数转换为“加 3”函数,使用柯里化:
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
不知何故,柯里化函数与Vectorize 不“兼容”,即它的行为就好像它根本没有被矢量化。
问题:对此我能做些什么?柯里化和向量化如何结合? (还有:出了什么问题?)
我找到了一种使用环境而不是Curry 的解决方法(很大程度上受到Hadley's add function 的启发),但我正在寻找一种不需要这种笨拙的“工厂”函数的更清洁的解决方案:
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)测试。
【问题讨论】:
-
在柯里化之前矢量化怎么样:
add3 <- functional::Curry(Vectorize(addAmount), amount = 3) -
@eipi10 我正要写同样的评论 :) 详细说明 OP 的方法不起作用的原因:R 中的 currification 过程有点奇怪。
functional::Curry(addAmount, amount = 3)返回一个只接受在自定义环境中处理的未命名参数 (...) 的函数。这不是Vectorize函数可以使用的东西。另一方面,对Vectorize(addAmount)返回的向量化函数进行柯里化是小菜一碟。 -
备注:如果您真的想对 curried 函数进行矢量化,您可以使用
x的命名包装器来实现:例如add3 = Vectorize(function(x){functional::Curry(addAmount, amount = 3)(x=x)}); add3(x=7:9) -
哦 - 我不知道为什么,但我从来没有想到在柯里化之前进行矢量化。我很乐意接受 eipi10 和 Jealie 的三个 cmets 的任何答案。谢谢你们!
标签: r functional-programming vectorization currying