Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print an R object to stderr in Rcpp?

Tags:

r

rcpp

I implemented a Python-style dictionary for R, but did not find a good way to raise an error when a given key does not have a value in the dictionary. Calling stop is easy enough, but I would like to tell the user which key has not been found by printing the R object. Right now I have:

Rcpp::Rcout << "Key not found: ";
Rcpp::print(key); # <-- how can I get this on stderr?
Rcpp::stop("Key error!");

This prints the message to stdout, but I'd rather have it on stderr. Probably I'm just missing a function that Rcpp provides?

Here's a MWE:

library(Rcpp)

sourceCpp(code='

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void test(SEXP key) {
  Rcpp::print(key);
  Rcpp::Rcerr << "This does not work: " << key << std::endl;
}

/*** R
test("x")
test(c(1,2,3))
*/

')
like image 415
Michael Kuhn Avatar asked Mar 14 '16 08:03

Michael Kuhn


2 Answers

This works just fine:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
std::string test(std::string key) {
  Rcpp::Rcerr << "Key not found: "<< key << std::endl;
  Rcpp::stop("Key error!");
  return key;
}

/*** R
test("x")
*/

Output:

Key not found: x
Error in eval(expr, envir, enclos) : Key error!

Edit:

OK, so you pass a SEXP that can be a single value or vector. I would suggest to cast that to a character vector:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void test(SEXP key) {
  CharacterVector key1 = as<CharacterVector>(key);
  Rcpp::Rcerr << "This does not work: " << key1 << std::endl;
}

/*** R
test(c("x", "y"))
test(1:3)
  */

Output:

> Rcpp::sourceCpp('E:/temp/ttt.cpp')

> test(c("x", "y"))
This does not work: "x" "y"

> test(1:3)
This does not work: "1" "2" "3"
like image 189
Roland Avatar answered Nov 12 '22 07:11

Roland


At the moment, it seems that this hack is the only way to go. It's not very efficient, as we go back from C++ to R to get the value as a nice string.

library(Rcpp)

sourceCpp(code='

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void test(SEXP key, Function generate_error) {
  std::string s = as<std::string>(generate_error(key));
  stop(s);
}

/*** R

generate_error <- function(key) {
  paste("Key not found:", capture.output(print(key)))
}

try( test("x", generate_error) )
try( test(c(1,2,3), generate_error) )
*/

')
like image 40
Michael Kuhn Avatar answered Nov 12 '22 06:11

Michael Kuhn