Hi Tal, On 16 August 2013 at 15:48, Tal Galili wrote: | Hello Dirk, | Your modifications/corrections are VERY helpful, thank you! (also, thank you | for the general kind words and ongoing support, they are much appreciated) | | One more question/improvement - is it possible to have it return whatever value | is inside the "label" attr?
Yes, sure. | For example, running the following would result in an error: | | /*** R | x <- list(a = 1, b=2, 6) | attr(x[[2]], "leaf") = TRUE | attr(x[[2]], "label") = 2 | extract_fun(x) | | ## output: | ## Error: expecting a string | /* | | Is there a way to either coerce/force "2" to become a string / or to return it | as what it is? (a numeric/double value)? | I thought that was what | label = as<std::string>(x.attr( "label" )) ; | was doing - but apparently it does not coerce non-string into strings | | | Any suggestions? Am at work and a little pressed for time, so just random thoughts: -- R has dynamic typing. An attribute could be 'anything' -- C++ is typed. You either must agree with yourself on a type, or do the casting. Converting int to string, or vice verse, is pretty common, and Google will show you examples. -- You could try to combine the approaches and just pick leaf elements and stick them into a a List object as SEXP (using wrap(...)). This is a nice example of a recursize list / tree walker. We'll get it polished and onto the Rcpp Gallery in no time. Dirk | | Tal | | | | | | | | | | | ----------------Contact | Details:------------------------------------------------------- | Contact me: tal.gal...@gmail.com | | Read me: www.talgalili.com (Hebrew) | www.biostatistics.co.il (Hebrew) | | www.r-statistics.com (English) | ---------------------------------------------------------------------------------------------- | | | | On Fri, Aug 16, 2013 at 2:47 PM, Dirk Eddelbuettel <e...@debian.org> wrote: | | | Tal, | | You were close. The error you got indicated that some of (our) wrapping | around (our) class String was missing somehow. String is pretty new; | Romain | just added it a few month ago under funding by Hadley -- and I am still | pretty unfamiliar with it. | | Which is why I always go back to std::string. So I converted your code | back, | which then built find but ran into one run-time error: you didn't test for | the attribute before extracting it. That is corrected too. So your | list-walker is below, with some extra verbose stdout prints. | | Hope this helps, it is a nice example and always was a very good question. | | Dirk | | | // Code first | | | #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_logical(RObject x){ | return TYPEOF(x) == LGLSXP && Rf_length(x) == 1 ; | } | | | bool is_leaf(RObject x){ | if( TYPEOF(x) != REALSXP ) return false ; | if( !is_logical( x.attr("leaf") ) ) return false ; | bool leaf = x.attr( "leaf" ) ; | return leaf; // either TRUE or FALSE. But often, if it exists - it is | TRUE. | } | | std::string get_label(RObject x){ | std::string label = "<empty>"; | if (x.hasAttribute("label")) { | label = as<std::string>(x.attr( "label" )) ; | } | return label; // either TRUE or FALSE. But often, if it exists - it is | TRUE. | } | | | void process( List data, std::vector<std::string>& results){ | Rcout << "List with " << data.size() << " elements\n"; | for( int i=0; i<data.size(); i++){ | if( is_list( data[i] ) ){ | // recurse | Rcout << "Recursing into list\n"; | process( data[i], results ) ; | } else if( is_leaf( data[i] ) ){ | Rcout << "Looking at leaf\n"; | // we want to collect them. we can use the NumericVector class | // wince we know this is a numeric vector. | std::string x_label = get_label(data[i]); | results.push_back(x_label); | } // else do nothing | } | } | | // [[Rcpp::export]] | std::vector<std::string> extract_fun(List x){ | std::vector<std::string> results ; | process(x, results) ; | return(results) ; | } | | /*** R | | x <- list(a = 1, b = 2, c = list(ca = 3, cb = 4, 5), 6) | attr(x[[1]], "leaf") = TRUE | attr(x[[1]], "label") = "leaf 1" | attr(x[[3]][[1]], "leaf") = TRUE | | attr(x[[2]], "leaf") = TRUE | attr(x[[2]], "label") = "leaf 2" | | str(x) | | extract_fun(x) | | */ | | | // Output below: | | > extract_fun(x) | List with 4 elements | Looking at leaf | Looking at leaf | Recursing into list | List with 3 elements | Looking at leaf | [1] "leaf 1" "leaf 2" "<empty>" | | | | -- | Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com | | -- Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com _______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel