Sets the value of -args from within an R session

I would like to use the evaluate package to simulate the execution of (many) r-scripts when writing outputs using evaluation. Evaluate is designed for this, and it works almost out of the box. However, when using Rscript, the user passes arguments through the --args command line, which are retrieved to R using the base::commandArgs .

Is there any sensible way to override the --args value from the current R session, so that an R script using base::commandArgs() will work as expected without having to change the script itself?

+4
source share
3 answers

I had an understanding of R guts and came up with some smelly intestines that I could play with.

The command line is copied from C argc / argv to the global variable C with this function in the source code:

 void R_set_command_line_arguments(int argc, char **argv) 

So, we need a little C shell to get around the fact that the first parameter is not a pointer:

 #include "Rh" #include "R_ext/RStartup.h" void set_command(int *pargc, char **argv){ R_set_command_line_arguments(*pargc, argv); } 

compile in the usual way:

 R CMD SHLIB setit.c 

Download, call:

 > dyn.load("setit.so") > commandArgs() [1] "/usr/lib/R/bin/exec/R" > invisible(.C("set_command",as.integer(2),c("Foo","Bar"))) > commandArgs() [1] "Foo" "Bar" 

and then commandArgs() will return this vector until you change it.

+6
source

Here is @spacedman's answer as a simple Rcpp based implementation. We have to do some gymnastics on the vector to get it in char** format:

 #include "Rcpp.h" #include "R_ext/RStartup.h" // [[Rcpp::export]] void setCmdArgs(std::vector<std::string> x) { std::vector<char*> vec(x.size()); for (unsigned int i=0; i<x.size(); i++) vec[i] = const_cast<char*>(x[i].c_str()); R_set_command_line_arguments(x.size(), static_cast<char**>(&(vec[0]))); } /*** R setCmdArgs(c("hello", "world")) commandArgs() setCmdArgs(c("good", "bye", "my", "friend")) commandArgs() */ 

If you save it in a file and pull it at once to sourceCpp() , then R is a snippet at the bottom:

 R> sourceCpp("/tmp/spacedman.cpp") R> setCmdArgs(c("hello", "world")) R> commandArgs() [1] "hello" "world" R> setCmdArgs(c("good", "bye", "my", "friend")) R> commandArgs() [1] "good" "bye" "my" "friend" R> 
+10
source

At the top of your script, you set commandArgs as TRUE , if you do not pass anything on the command line, the variable will be 0 , so use the if to assign some values ​​if you are not actually passing command line arguments. If you need to be careful when using default values, you can set a flag to print a message when using the default values ​​for command line arguments.

 args <- commandArgs(TRUE) argDefault <- FALSE if( length(args) == 0 ){ args <- whatever you want argDefault <- TRUE } res <- 2 * args[1] if( argDefault ) simpleWarning(message="No command args were passed: Use of default values") 
+1
source

Source: https://habr.com/ru/post/1487212/


All Articles