6

Here is my code. It produces infinite loop, because value of something variable does not change within captured error. Is it supposed to be this way? How can I fix it so that value of something changes to FALSE?

something <- TRUE
counter <- 1
while(something){
  print(counter)  
  tryTest = tryCatch(
    {
      arima(rep(1,3), order = c(1,0,0))
    }, 
    warning = function(w) {

      print('this is warning')
      print(w)
    },
    error = function(e) {
      something <- FALSE
      print('this is error')
      print(e)
    },
    finally = {}
  )
  counter <- (counter +1)
}
user1700890
  • 7,144
  • 18
  • 87
  • 183
  • 3
    Define your warning function as: `warning = function(w) { something <<- FALSE print('this is warning') print(w) } ` ,where "<<-" - *"This operator assigns the variable to the parent scope. It first looks for the variable in the parent scope and if it can’t find one then it creates a new one in the parent scope."* - http://www.studytrails.com/r/core/assignmentoperator/ – nadizan Jan 22 '18 at 22:18
  • 1
    @nadizan, I just tried it and it does not work, still infinite loop – user1700890 Jan 22 '18 at 22:32
  • @nadizan the problem with your suggestion is that the parent scope of the lambda is still inside the tryCatch function and is not the outer scope. – Mosquite Jan 22 '18 at 22:55
  • As a side note. On error, the return value of the error function is returned by `tryCatch` on error. you could always use that to stop your loop. Condition on `tryTest` being non NULL to continue your loop. Just make sure to return something non null on a warning. – Mosquite Jan 22 '18 at 22:59
  • @user1700890, this works completely fine for me. `something <- TRUE counter <- 1 while(something){ print(counter) tryTest = tryCatch( { arima(rep(1,3), order = c(1,0,0)) }, warning = function(w) { something <<- FALSE print('this is warning') print(w) }, error = function(e) { something <- FALSE print('this is error') print(e) }, finally = {} ) counter <- (counter +1) }` – nadizan Jan 23 '18 at 10:36
  • @nadizan you are right. Thank you! Funny how I wrote about catching error, but you put code into warning block. This arima generates both error and warning, and if you add `something <<-FALSE` to error block, it would not work. This is I guess a bit different issue: https://stackoverflow.com/questions/48391287/trycatch-block-in-r-returning-variable?noredirect=1#comment83770717_48391287 – user1700890 Jan 23 '18 at 15:18
  • 1
    See also: https://stackoverflow.com/questions/38482937/variable-scope-in-r-trycatch-block-is-necessary-to-change-local-variable-de – climatestudent Aug 16 '21 at 12:00

1 Answers1

8

This happens because the environment of something in the outer code is different from the environment of something in your lambda:

function(e) {
    something <- FALSE
    print('this is error')
    print(e)
}

So setting something <- FALSE in your lambda actually sets a different something then in the outer code. To fix this you can either 1) make something a global variable or 2) create an environment to use something in.

1)

assign("something", TRUE, env=globalenv())

to set the variable and

get("something", env=globalenv())

to access the variable.

You can also set something inside your lambda in the same way:

assign("something", FALSE, env=globalenv())

or

2)

First create a new variable:

env=new.env()

Then set and access your variable in a similar way as before:

assign("something", TRUE, env=env)
get("something", env=env)

You can assign something inside your lambda with:

assign("something", FALSE, env=env)

Using env is possible because R copies variables to child environments. However if you set a variable in a child environment (like when you did `somethi

Mosquite
  • 588
  • 1
  • 4
  • 15