Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return result invisibly

Tags:

c++

r

rcpp

I’m trying to return a result (in fact, NULL) invisibly from a C++ function via Rcpp. Unfortunately I am unable to find out how to do this. My first attempt was to set R_Visible but this global variable is no longer exported; next, I tried calling do_invisible (the primitive that invisible calls) directly but, likewise, it’s not exported (and to be honest I’m unsure how to call it correctly anyway).

I then went the roundabout way, calling R’s base::invisible from Rcpp via an Rcpp::Function. My code is now something like this:

Rcpp::Function invisible = Rcpp::Environment("package:base")["invisible"];

// [[Rcpp::export]]
SEXP read_value(Rcpp::XPtr<std::vector<int>> x, int index) {
    try {
        return Rcpp::wrap(x->at(index));
    } catch (std::out_of_range const&) {
        return invisible(R_NilValue);
    }
}

This compiles and executes. Unfortunately, the invisible call is simply ignored; when calling the function from R with an invalid index, it prints NULL. I would like it to print nothing.

For testing:

// [[Rcpp::export]]
Rcpp::XPtr<std::vector<int>> make_xvec() {
    return Rcpp::XPtr<std::vector<int>>{new std::vector<int>{1, 2, 3}};
}

/*** R
xv = make_xvec()
read_value(xv, 1)
invisible(read_value(xv, 4)) # Works
read_value(xv, 4)            # Doesn’t work
*/
like image 309
Konrad Rudolph Avatar asked Jan 08 '18 13:01

Konrad Rudolph


People also ask

What does invisible () do in R?

The invisible() function in R Programming Language is used to make the printing statements invisible which means the printing statements will not appear.

What does plot return r?

The base R plot function returns NULL , since its main purpose is to draw a plot. This isn't helpful if you want to use it in piped code: instead it should invisibly return the plot data to be piped on to the next step.


1 Answers

Hm. "Ultimately" we always get SEXP .Call(id, SEXP a, SEXP b, ...) and that ends up (via Rcpp Attributes) with something like

R> rqdb::qdbConnect
function () 
{
    .Call(`_rqdb_qdbConnect`)
}
<environment: namespace:rqdb>
R> 

which when we call it gives us

R> qdbConnect()
[1] TRUE
R> invisible(qdbConnect())
R> 

Can't you just wrap another layer at the R side and call it a day?

I think the key really is that a void function is possible, but the default is something as the SEXP. And C++ only has return so you need R for the invisible part.

like image 73
Dirk Eddelbuettel Avatar answered Sep 20 '22 21:09

Dirk Eddelbuettel