R disable traceback after evaluating stop function - r

I am using a function for error handling, which is used in another function. This looks like:
foo <- function() {
fooo <- function () {
stop('Hello World')
}
fooo()
}
Now upon calling foo(), R will provide a traceback option. However, if only fooo() is called (after running it as a stand alone function first) the stop() function will produce an error message without traceback. Ideally, I would prevent R from generating a traceback option and solely print the error message to the console. So.. How do I do this?

Related

Return integer using TclTK from C library

I have C code that uses Tcl/Tk library. I then create a library using this C code which is then linked to R language package. I have a function in the C code:
int doSomething(){
if(TRUE){
return TCL_OK;
else{
TCL_RESULT3("Error")
return TCL_OK;
}
Currently, I use TCL_RESULT3("Error") in the C code, and then in R check if result <- tclvalue(tcl(...)) #calls doSomething() returns a string with Error:
if (startsWith(result, "Error"))
{
return(FALSE)
}
return(TRUE)
and base further actions in R on the returned value.
However, even though there is an error, I still call TCL_OK because TCL_ERROR produces something that R cannot seem to handle (at least it is not straightforward). My question is if it is possible to restructure my function as:
int doSomething(){
if(TRUE){
return TCL_OK;
else{
return TCL_ERROR;
}
and have R understand what is being returned. Currently, if TCL_OK is returned, then result will be an empty string "". If TCL_ERROR is returned, then result will yield: Error in structure(.External(.C_dotTclObjv, objv), class = "tclObj") : [tcl] . which R does not know how to handle.
Is it possible to have R handle such an error (i.e. return a value of FALSE if this error pops up) or is checking for an error message using TCL_RESULT3() in conjunction with TCL_OK the best method for such a process?
When your C code returns TCL_ERROR (instead of TCL_OK) that's an error condition, which is logically like an exception in other languages. Can R handle those? Yes (apparently; I know very little R). Here's one way (there are others, of course; the right choice depends on what you're doing and the likely cause of the exception).
result <- tryCatch(
{
# This is where you put in the code to call into Tcl
tclvalue(tcl(...)) # calls doSomething()
},
error = function(err) {
message(paste("error occurred in Tcl code:", err))
return(NaN) # Need an alternative result value here
}
)
Note that if you're calling an arbitrary Tcl command, you pretty much have to handle exceptions. Failures are a fact of life, and you need to allow for them in robust code.

catch a deliberately generated error by stop() inside a function in a tryCatch

fn2 <- function(args2){
output
}
fn1 <- function(arg1){
tryCatch({
output = do.call(fn2, args2_list)
}, error = function(e){
if(str_detect(e$message, 'err_msg', negate = FALSE)){
<do something>
}
stop(e$message)
})
}
I have some code structured as shown above. fn2 gives an error but is not reproducible as of now. I only know what the error message is. So I have placed a tryCatch to capture the error and check if it's the same message for which I need to get more context and do some handling for it.
But I need to write a test using testthat which tests that when the error message is returned it only does the handling if the string match is correct else does not. How can I do so?
It seems I need to mock fn2 and return the error message which gets caught by the tryCatch block. I tried using stop('err_msg') in the mock function but it is not caught by the tryCatch block it seems.

Limit the calls to an R function in case of warning

I have a function foo:
foo<-function(x,y,z){
{
some initial R code
}
eresult<-tryCatch(expr= eresult<-eclat(),
warning = function(w){
writelog(paste(w),logfile)
result<-eclat()
return(result)
},
error=function(e){
writelog(paste(e),logfile)
})
}
I am calling foo in loop using mapply over two columns of a data.frame df and one fixed argument "db_credential" for parameter z.
df<-data.frame(a=(1,2),b=c(2,3))
tryCatch(expr=mapply(FUN=foo,df$a,df$b,"db_credential"),
warning=function(w){writelog(paste(w),logfile)},
error=function(e){writelog(paste(e),logfile)})
On execution of this set of code, the eclat function throws a warning due to some choice of parameters for the function call of eclat. So foo is being called 4 times.
Is there a way by which I can restrict the call to foo only 2 times [to avoid the execution of "some initial R code" which involves fetching data from database and it's transformation] and yet handle all the warnings and errors.
I just want that the eclat function should be called again with the same parameters to produce the output rather than the control being thrown to the warning part of mapply call.

R: Exit from the calling function

In R, is there a way to exit from the calling function and return a value? Something like return(), but from the parent function?
parent <- function(){
child()
# stuff afterward should not be executed
}
child <- function(){
returnFromParent("a message returned by parent()")
}
It seems stop() is doing something like that. What I want to do is to write a small replacement for stop() that returns the message that stop() writes to stderr.
Update after G5W's suggestion: I have a large number of checks, each resulting in a stop() if the test fails, but subsequent conditions cannot be evaluated if earlier checks fail, so the function must exit after a failing one. To do this 'properly', I would have to build up a huge if else construct, which I wanted to avoid.
Got it. I guess I was looking for something like this:
parent <- function(){
parent_killing_child()
print("do not run this")
}
parent_killing_child <- function(){
do.call(return, list("my message"), envir = sys.frame(-1))
}
parent()
Thanks for all the advices.
Disclaimer: This sounds a XY problem, printing the stop message to stdout has few to no value, if interactive it should not be a problem, if in a script just use the usual redirection 2 > &1 to write stderr messages to stdout, or maybe use sink as in answer in this question.
Now, if I understood properly what you're after I'll do something like the following to avoid too much code refactoring.
First define a function to handle errors:
my_stop <- function() {
e <- geterrmessage()
print(e)
}
Now configure the system to send errors to your function (error handler) and suppress error messages:
options(error = my_stop)
options(show.error.messages=FALSE)
Now let's test it:
f1 <- function() {
f2()
print("This should not be seen")
}
f2 <- function() {
stop("This is a child error message")
}
Output:
> f1()
[1] "Error in f2() : This is a child error message\n"
For the parent function, make a list of tests. Then loop over the tests, and return your message at the first failed test. Subsequent tests will not be executed after the first failure.
Sample code:
test1 <- function(){criteria <- T; return(ifelse(criteria,T,F))}
test2 <- function(){criteria <- F; return(ifelse(criteria,T,F))}
test3 <- function(){criteria <- T; return(ifelse(criteria,T,F))}
parent <- function() {
tests <- c('test1', 'test2', 'test3')
for (i in 1:length(tests)) {
passed <- do.call(tests[i],args = list())
#print(passed)
if (!passed){
return(paste("Testing failed on test ", i, ".", sep=''))
}
}
return('Congrats! All tests passed!')
}
parent()
Update
Kudos to #chris for their clever application of do.call() in their successful solution.
In five years since then, the R team has released the rlang package within the tidyverse, which provides the apt function rlang::return_from() in tandem with rlang::return_to().
While base::return() can only return from the current local frame,
these two functions will return from any frame on the current
evaluation stack, between the global and the currently active context.
They provide a way of performing arbitrary non-local jumps out of the
function currently under evaluation.
Solution
Thus, you can simply do
child <- function() {
rlang::return_from(
# Return from the parent context (1 frame back).
frame = rlang::caller_env(n = 1),
# Return the message text.
value = "some text returned by parent()"
)
}
where the parent is identified via rlang::caller_env().
Results
When called from a parent() function
parent <- function() {
child()
# stuff afterward should not be executed
return("text that should NOT be returned by parent()")
}
the child() function will force parental behavior like this:
parent()
#> [1] "some text returned by parent()"
Bonus
See my solution here for throwing an error from a parent (or from any arbitrary "ancestor").

Error: could not find function "nnn.R"

I sourced my function nnn.R using the line :
source("nnn.R")*
and did not get any errors, but when I try to run it, this is what I get:
Error: could not find function "nnn"*
this all what the function has inside
function (x) is.null(x)
nnn.R is a file, not a function. The file must contain a function, defined as:
nnn <- function(x) {
return (is.null(x))
}
Note that nnn.R may contain several function definitions. See for instance this tutorial.

Resources