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? 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? 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 >
_______________________________________________ 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