How to combine Curry () with Vectorize ()?

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).

+5
source share
1 answer

You can vectorize before currying:

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

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

+2
source

Source: https://habr.com/ru/post/1269721/


All Articles