Consider the following function:
addAmount <- function(x, amount) { stopifnot(length(x) == 1) return(x + amount) }
It can be used to add some amount to x :
> addAmount(x = 5, amount = 3) [1] 8 > addAmount(x = 2, amount = 3) [1] 5
However, x must have a length of 1:
> addAmount(x = 7:9, amount = 3) Error: length(x) == 1 is not TRUE
I added this restriction intentionally for illustration.
Using Vectorize , you can go to the vector for x :
> Vectorize(addAmount)(x = 7:9, amount = 3) [1] 10 11 12
So far so good.
However, I would like to turn the addAmount function into the add 3 function using currying:
add3 <- functional::Curry(addAmount, amount = 3)
This works as expected if x is 1 and fails (as expected) if x not 1:
> add3(x = 5) [1] 8 > add3(x = 7:9) Error: length(x) == 1 is not TRUE
The problem is this: add3 cannot be vectorized:
> Vectorize(add3)(x = 7:9) Error: length(x) == 1 is not TRUE
Be that as it may, the curried function is not "compatible" with Vectorize , i.e. behaves as if she had not been vectorized at all.
Question: What can I do about this? How to combine currying and vectorization? (And: what is wrong?)
I found a workaround (a strongly inspired Hadley add function ) using environments instead of Curry , but I am looking for a cleaner solution that does not require such awkward "factory" functions:
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
Tested with R 3.4.1 and functional package (version 0.6).