Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture an uncapturable error

Tags:

r

I want to capture an error from D%4 and move on. The error is:

Error: unexpected input in "D%4"

Typically if a function is being called the following works:

capture_warn_error <- function(x){
    tryCatch({
        x
    }, warning = function(w) {
        w
    }, error = function(e) {
        e
    })
}

capture_warn_error(D%4) 

But the no recovery is possible as `D%4 shuts down everything immediately:

## > capture_warn_error(D%4)
## Error: unexpected input in "capture_warn_error(D%4)"

Is there anyway to capture such a stubborn beast and move on? I know D%4 isn't an object but this works for other non objects:

capture_warn_error(means)
## <simpleError in doTryCatch(return(expr), name, parentenv, handler): object 'means' not found>

It's be nice to:

  1. Understand why D%4 is unrecoverable vs means
  2. Find a way to recover still and capture D%4's error
like image 947
Tyler Rinker Avatar asked Oct 28 '15 18:10

Tyler Rinker


2 Answers

As others have stated it is because text typed at the console gets passed to the parser. D%4 fails the rigid test of being valid R expression, because a single % is not valid inside an R name (although it would create a token that would be interpreted as a user defined function if there were a closing %) and % is also not a function name (although%% is). The error occurs in the processing of the argument to your function and so it never reached the internal tryCatch-call. I originally didn't get the idea that you wanted to parse this input as R code, so thought that simply wrapping readline as the single argument to be be input may satisfy:

mfun <- function( x=readline(">>+ ") ){ print(x) }
mfun()
#-----screen will display--------
>>+ D%4
[1] "D%4"

If I'm wrong about your intent, as it appears on a re-read of the question, then this would build that input mechanism into your capture_error function. This brings those characters in as unparsed text and then does the parse-eval within the tryCatch enclosure:

> capture_warn_error <- function(x=readline(">>+ ")){
+     tryCatch({ eval(parse(text=x))
+         
+     }, warning = function(w) {
+         w
+     }, error = function(e) {
+         e
+     })
+ }
> capture_warn_error(D%4)
Error: unexpected input in "capture_warn_error(D%4)"
> capture_warn_error()
>>+ D%4
<simpleError in parse(text = x): <text>:1:2: unexpected input
1: D%4
     ^>
> err <- capture_warn_error()
>>+ D%4
> err
<simpleError in parse(text = x): <text>:1:2: unexpected input
1: D%4
     ^>

> err <- capture_warn_error()
>>+ D %% 4
> err
<simpleError in D%%4: non-numeric argument to binary operator>
> err <- capture_warn_error()
>>+ 4 %smthg% 2
> err
<simpleError in eval(expr, envir, enclos): could not find function "%smthg%">

As demonstrated above, it does require that you not provide any input in the argument list to the function call, but rather make the capture-call with an empty argument list.

like image 85
IRTFM Avatar answered Nov 09 '22 10:11

IRTFM


You could set up a function to capture input and parse it, wrapping it in your capture_warn_error function.

getfunction <- function(){
  x<-readline()
  if(x == "exitnow"){return("bye!")}
  print(capture_warn_error(eval(parse(text = x))))
  getfunction()
}

They'll now be typing at a non-console prompt, but it will work okish - assignments will need work.

1+1
[1] 2
d%e
<simpleError in parse(text = x): <text>:1:2: unexpected input
1: d%e
     ^>
exitnow
[1] "bye!"
like image 3
jeremycg Avatar answered Nov 09 '22 11:11

jeremycg