3

How can I return a value in a function, through another function, see example here :

first_try <- function() eval(return(1),parent.frame())
second_try <- function() source(textConnection("return(2)"),parent.frame())

fun1 <- function(x){
  first_try()
  second_try()
  3
}

fun1()
# [1] 3

fun1 should stop at first_try and return 1, and if second_try had worked it would have returned 2.

Is such a thing possible ?

moodymudskipper
  • 46,417
  • 11
  • 121
  • 167
  • I am not sure whether I understand the question correctly. If you want to return at `first_try`, why do you need `second_try` and the `3`. If the return value depends on something else, why not use `if-else`? – mt1022 Feb 22 '18 at 14:27
  • `3` is just there to show that neither `first_try` nor `second_try` work. In practice this function will be wrapped into a condition, so there'll be code afterwards, abbreviated into `3` here. Is it clearer this way ? – moodymudskipper Feb 22 '18 at 14:33
  • If so, why not try `if(a){return(1)}else if(b){return(2)}; 3;`? – mt1022 Feb 22 '18 at 14:35
  • It's a matter of readability, programming convenience, and curiosity, I'm not stuck in my work. I have a function that will always be followed or embedded by a return call, so it makes sense to me to put the return call inside. – moodymudskipper Feb 22 '18 at 14:53

1 Answers1

0

rlang::return_from() provides this functionality :

return_a <- function() rlang::return_from(parent.frame(),"a")

fun <- function(){
  return_a()
  "b"
}
fun()
#> [1] "a"

Created on 2020-01-03 by the reprex package (v0.3.0)

We can also fix my first try by quoting return(1) and use rlang::eval_bare()rather than base::eval()

From the doc :

eval_bare() is a lower-level version of function base::eval(). Technically, it is a simple wrapper around the C function Rf_eval(). You generally don't need to use eval_bare() instead of eval(). Its main advantage is that it handles stack-sensitive (calls such as return(), on.exit() or parent.frame()) more consistently when you pass an enviroment of a frame on the call stack.

first_try <- function() rlang::eval_bare(quote(return(1)),parent.frame())
fun1 <- function(x){
  first_try()
  second_try()
  3
}

fun1()
#> [1] 1

Created on 2020-01-03 by the reprex package (v0.3.0)

moodymudskipper
  • 46,417
  • 11
  • 121
  • 167