A taste of functional programmming in Rcpp11
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
@kevinushey requested some functional programming in Rcpp11 and provided initial versions of map
and filter
. map
is actually doing exactly the same thing as mapply
so I added map
as a synonym to mapply
so that we can do (see this previous post for details):
// [[Rcpp::export]] NumericVector mapply_example(NumericVector x, NumericVector y, double z){ auto fun = [](double a, double b, double c){ return a + b + c ;} ; return map( fun, x, y, z ) ; }
filter
takes a sugar expression (e.g. a vector) and a function predicte and only keeps the elements of the vector for which the predicate evaluates to true
. Here is a simple example:
// [[Rcpp::export]] NumericVector filter_example(NumericVector x ){ auto positives = [](double a){ return a >= 0 ;} ; return filter(x, positives ) ; }
I’ve also put in the negate
function. Intuitively enough, it takes a function (e.g. a lambda) and returns a function that negates it. For example, we can expand the previous example using both the positives
lambda and a negated version of it:
// [[Rcpp::export]] List filter_example_2(NumericVector x ){ auto positives = [](double a){ return a >= 0 ;} ; return list( _["+"] = filter(x, positives ), _["-"] = filter(x, negate(positives) ) ) ; }
We can also compose two functions:
// [[Rcpp::export]] NumericVector filter_example_3(NumericVector x ){ auto small = [](double a){ return a < 4 ;} ; auto square = [](double a){ return a * a ;} ; return filter(x, compose(square, small) ) ; }
But since I've been spoiled by magrittr
and dplyr
, I've put in this alternative way to compose the two functions:
// [[Rcpp::export]] NumericVector filter_example_4(NumericVector x ){ auto small = [](double a){ return a < 4 ;} ; auto square = [](double a){ return a * a ;} ; return filter(x, _[square] >> small ) ; }
_
turns square
into a Rcpp::functional::Functoid
which implements operator>>
. Functoid
can also be negated by the operator!
:
// [[Rcpp::export]] NumericVector filter_example_5(NumericVector x ){ auto small = [](double a){ return a < 4 ;} ; auto square = [](double a){ return a * a ;} ; auto fun = _[square] >> small ; return filter(x, !fun ) ; }
I'm not sure this is going to be of any use or even if this will stay, but that was fun.
$ Rcpp11Script /tmp/filter.cpp > x <- seq(-10, 10, by = 0.5) > filter_example_1(x) [1] 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 [16] 7.5 8.0 8.5 9.0 9.5 10.0 > filter_example_2(x) $`+` [1] 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 [16] 7.5 8.0 8.5 9.0 9.5 10.0 $`-` [1] -10.0 -9.5 -9.0 -8.5 -8.0 -7.5 -7.0 -6.5 -6.0 -5.5 -5.0 -4.5 [13] -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 > filter_example_3(x) [1] -10.0 -9.5 -9.0 -8.5 -8.0 -7.5 -7.0 -6.5 -6.0 -5.5 -5.0 -4.5 [13] -4.0 -3.5 -3.0 -2.5 -2.0 2.0 2.5 3.0 3.5 4.0 4.5 5.0 [25] 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5 10.0 > filter_example_4(x) [1] -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 > filter_example_5(x) [1] -10.0 -9.5 -9.0 -8.5 -8.0 -7.5 -7.0 -6.5 -6.0 -5.5 -5.0 -4.5 [13] -4.0 -3.5 -3.0 -2.5 -2.0 2.0 2.5 3.0 3.5 4.0 4.5 5.0 [25] 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5 10.0
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.