Consider the following code:
test1 <- "a"
test2 <- "a"
tryCatch(stop(), error= function(err){
print(test1)
print(test2)
test1 <- "b"
test2 <<- "b"
})
Result:
print(test1)
[1] "a"
print(test2)
[1] "b"
The value of variable test1 is visible within the tryCatch block, but changing it with "<-" operator does not affect its value outside the tryCatch block.
If a new value is assigned with <<- it has the desired effect. Why?
Is using the <<- operator within the tryCatch block a recommended way to change the value of a local variable outside this block? Could there be some unexpected sideffects?
EDIT: Based on a Bernhard answer, does the following code make up for the right approach to this problem?
test1 <- "a"
test2 <- "a"
new_values<-tryCatch(
{
print("hello")
stop()
}
, error= function(err){
# I want to change the test1 and test 2 variables to "b" only if error occurred.
test1 <- "b"
test2 <- "b"
return(list(test1=test1,test2=test2))
})
if (is.list(new_values))
{
test1<-new_values$test1
test2<-new_values$test2
}
Result:
> print(test1)
[1] "b"
> print(test2)
[1] "b"
The '<<-' is made for side effects that do not belong to R. Use it never, or only if memory or speed force you to do so. A block has it's own scope and if you want to give data from within a block to the 'outside' environement, that there is return() for that task:
test2 <- "a"
test2 <- tryCatch(stop(), error= function(err){
somevariable <- "b"
return(somevariable)
})
This makes it clear to everyone, that toplevel test2 is set to "a" and then, that toplevel test2 is set to something else. With '<<-' it happens easily, that some function changes toplevel test2 and someone wonders, why toplevel test2 has been changed at all. Just don't <<-.
If there is a need to return more than one result, return a list or an object of the results.
EDIT: The OP has pointed out that you need to be carefull with the return statements, as they do not only end the current block, but also the current function. A possible solution is, to run the computations in functions instead of simple blocks. The following example should illustrate this:
safediv <- function(a, b){
normalDo <- function(a, b){
return(list(value=a/b, message=NULL))
}
exceptionalDo <- function(err){
return(list(value=NaN, message="caught an error! Change global variable?"))
}
results <- tryCatch(normalDo(a, b), error=exceptionalDo)
print("safediv is still running after the returns within the functions.")
return(results)
}
# try it out
safediv(5, 3)
safediv(5, 0)
safediv(5, "a")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With