Site icon R-bloggers

A taste of functional programmming in Rcpp11

[This article was first published on R Enthusiast and R/C++ hero, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
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
To leave a comment for the author, please follow the link and comment on their blog: R Enthusiast and R/C++ hero.

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.