Thanks Romain and Dirk! I am currently (slowly) working on developing a package where I would need some of these skills for specific bottleneck functions. I will get to the stage of using your code probably in something between 2 to 5 weeks (I hope). Once I reach it I will gladly share my progress.
With regards, Tal ----------------Contact Details:------------------------------------------------------- Contact me: [email protected] | Read me: www.talgalili.com (Hebrew) | www.biostatistics.co.il (Hebrew) | www.r-statistics.com (English) ---------------------------------------------------------------------------------------------- On Tue, Jul 23, 2013 at 3:23 PM, Romain Francois <[email protected]>wrote: > Hello Tal, > > I'm trying to express this with the tools available in Rcpp 0.10.3. (And > adding some tools for later versions too, like is<>). > > Here is how I would do the first problem: > > First break down into functions. We need : > - something that tells me if a given R object is a list. With Rcpp devel, > we could use is<List> but for now we can write it as: > > bool is_list(RObject x){ > return TYPEOF(x) == VECSXP ; > } > > I've added the is<> so that you don't need to know about TYPEOF or VECSXP. > But here we are essentially mimicking typeof( x ) == "list" > > - We need something to tell me if something is a single string: > > bool is_string(RObject x){ > return TYPEOF(x) == STRSXP && Rf_length(x) == 1 ; > } > > agai, with Rcpp devel, we could express this like this: is<String>( x ) > instead. > > - We need something that tells if an object has a type attribute that is > equal to fun. R lets us do that easily, but we have to pay that flexibility > in C++. What I came up with is this: > > bool is_fun(RObject x){ > // is this a numeric vector > if( TYPEOF(x) != REALSXP ) return false ; > > // is the type attribute a string ? > if( !is_string( x.attr("type") ) ) return false ; > > // test the string > String type = x.attr( "type" ) ; > return type == "fun" ; > } > > - Then, we need a recursive function that goes through elements of a list. > For collecting results, I'm choosing to pass a std::vector by reference. So > there are two things to learn here: > - pass by reference > - std::vector > you'll find many resources online to teach you these things. > > void process( List data, std::vector<double>& results ){ > for( int i=0; i<data.size(); i++){ > if( is_list( data[i] ) ){ > // recurse > process( data[i], results ) ; > } else if( is_fun( data[i] ) ){ > // we want to collect them. we can use the NumericVector class > // wince we know thius is a numeric vector. > // (it is tested in is_fun) > NumericVector x = data[i] ; > > // loop through the values and add them to the results vector > for( int j=0; j<x.size(); j++){ > results.push_back( x[j] ) ; > } > } // else do nothing > } > } > > > - Finally, we need something that you can call from R. It takes a list as > input, and returns a numeric vector. > > // [[Rcpp::export]] > NumericVector extract_fun(List x){ > std::vector<double> results ; > process(x, results) ; > return wrap(results) ; > } > > > Here is the full script: > > #include <Rcpp.h> > using namespace Rcpp ; > > bool is_list(RObject x){ > return TYPEOF(x) == VECSXP ; > } > > bool is_string(RObject x){ > return TYPEOF(x) == STRSXP && Rf_length(x) == 1 ; > } > > bool is_fun(RObject x){ > if( TYPEOF(x) != REALSXP ) return false ; > if( !is_string( x.attr("type") ) ) return false ; > String type = x.attr( "type" ) ; > return type == "fun" ; > } > > void process( List data, std::vector<double>& results ){ > for( int i=0; i<data.size(); i++){ > if( is_list( data[i] ) ){ > // recurse > process( data[i], results ) ; > } else if( is_fun( data[i] ) ){ > // we want to collect them. we can use the NumericVector class > // wince we know thius is a numeric vector. > // (it is tested in is_fun) > NumericVector x = data[i] ; > > // loop through the values and add them to the results vector > for( int j=0; j<x.size(); j++){ > results.push_back( x[j] ) ; > } > } // else do nothing > } > } > > // [[Rcpp::export]] > NumericVector extract_fun(List x){ > std::vector<double> results ; > process(x, results) ; > return wrap(results) ; > } > > /*** R > > > x <- list(a = 1, b = 2, c = list(ca = 3, cb = 4, 5), 6) > attr(x[[1]], "type") = "fun" > attr(x[[3]][[1]], "type") = "fun" > x > > extract_fun(x) > > */ > > You should be able to sourceCpp it and get the expected result. > > > > I let you do 2 and 3 as an exercize with what you learn from this. > Hints: > - For 2). you don't need to collect results, so your process can look like > this: > > void process( List data ){ > // ... > } > > I let you update the body to do what you wanted > > - For 3). There are several ways to do this in C++. you could use a > reference to an int, a static variable within the function. You could even > use some data that lives in an R environment, using the Environment class. > > Whatever you come up with, feel free to share. Those examples are nice > examples of something that is relatively easy to do when you start to be > Rcpp fluent, but not so easy otherwise. > > Romain > > > Le 20/07/13 18:44, Tal Galili a écrit : > >> Hello dear Rcpp users, >> >> First - I'd like to say that I took Hadley and Romain's workshop at the >> useR conference this year, and I am very excited about trying out Rcpp - >> this project looks AMAZING. >> >> Second - this is my first post, and I apologize if my question is too >> basic. To my defense, I tried looking through this mailing list / >> googled before asking, and read through Hadley's github chapter on Rcpp. >> >> The questions: >> >> I am looking to understand better how List objects can be navigated, >> their elements accessed, and manipulated - using Rcpp. >> >> For example, here is an R list object: >> >> x <- list(a = 1, b = 2, c = list(ca = 3, cb = 4, 5), 6) >> attr(x[[1]], "type") = "fun" >> attr(x[[3]][[1]], "type") = "fun" >> x >> >> I would like to create two types of functions: >> 1) A function that will go through "x" and will *_RETURN_* all of the >> >> elements within it that are of type "fun". >> In R I would do it like this: >> >> return_fun <- function(x) { >> fun_nubmers <- numeric() >> for(i in seq_along(x)) { >> if(class(x[[i]]) == "list") { >> fun_nubmers <- c(fun_nubmers, return_fun(x[[i]])) >> } else { >> if(!is.null(attr(x[[i]], "type"))) { >> if(attr(x[[i]], "type") == "fun") fun_nubmers <- >> c(fun_nubmers, x[[i]]) >> } >> } >> } >> return fun_nubmers >> } >> return_fun(x) # output: 1 3 >> >> But in Rcpp there are many parts to this R function that I don't know >> how to do. I don't know how to access the attributes of a sub-element >> within a List, I don't know how to check if that attribute is null or >> not, etc. So any suggestions on either reading material (or better yet - >> an example of how this function might be created in Rcpp would be great. >> >> >> 2) A function that will go through "x" and will *_CHANGE_* all of the >> >> elements within it that are of type "fun". For example, adding 1 to them. >> In R I would do it like this: >> >> add1_fun <- function(x) { >> for(i in seq_along(x)) { >> if(class(x[[i]]) == "list") { >> x[[i]] <- add1_fun(x[[i]]) >> } else { >> if(!is.null(attr(x[[i]], "type"))) { >> if(attr(x[[i]], "type") == "fun") x[[i]] <- x[[i]] + 1 >> } >> } >> } >> x >> } >> add1_fun(x) >> return_fun(x) # output: 1 3 >> return_fun(add1_fun(x) ) # output: 2 4 >> >> >> 3) Is it possible to work with some "global" variable from within a >> recursive Rcpp function? >> For example: >> >> >> count_till_5 <- function() { >> if(!exists("global_var")) global_var = 0 >> >> if(global_var <5) { >> global_var <<- global_var+1 >> count_till_5() >> } >> } >> count_till_5() >> global_var >> >> Is there a way to create something like this with Rcpp? >> >> >> Thanks in advance for any help. >> >> With regards, >> Tal >> > > -- > Romain Francois > Professional R Enthusiast > +33(0) 6 28 91 30 30 > > R Graph Gallery: > http://gallery.r-enthusiasts.**com<http://gallery.r-enthusiasts.com> > > blog: http://blog.r-enthusiasts.com > |- http://bit.ly/13SrjxO : highlight 0.4.2 > `- http://bit.ly/10X94UM : Mobile version of the graph gallery > >
_______________________________________________ Rcpp-devel mailing list [email protected] https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
