Home > Enterprise >  Put break/next statements inside functions in R
Put break/next statements inside functions in R

Time:08-30

I have a complex condition (including side effects) for deciding if go next in a loop, so I would like to extract the logic in a function.

CRAN checks return the following warning:

Found the following significant warnings:
     Note: break used in wrong context: no loop is visible 
     Note: next used in wrong context: no loop is visible 

I have tried doing something like reported in the following minimal reprex, but it returns an error.

# comented code are not needed to reproduce the issue, they are 
# just a sample of some compelxity I would like to extract from the
# cycle using `b`
b <- function() {
  # cat("Doing something complex w/ side effect") 
  # complex_cond <- TRUE
  # if (complex_cond) {
    break
  # } else {
  #   cat("Perform compelx cycle computation")
  # }
}

res <- for (j in letters[1:2]) {
  cat(j)
  for (i in 1:2) {
    cat(i, "\n")
    b()
  }
}
#> a1
#> Error in b(): no loop for break/next, jumping to top level

expected <- for (j in letters[1:2]) {
  cat(j)
  for (i in 1:2) {
    cat(i, "\n")
    break
  }
}
#> a1 
#> b1

res |> identical(expected)
#> Error in identical(res, expected): object 'res' not found

Created on 2022-08-29 by the reprex package (v2.0.1)

Independently from the fact that it could be helpful or not, nor if it could be a good practice (surely not! :-) ), do you know if it is possible to do that or, if not, why?

Thank you! :-)

CodePudding user response:

Although you can't break out of a loop from within a function you can return early from an outer function from within an inner function using callCC. See R - evaluating return() in parent environment for an example.

However, here we are just concerned with a conditional break for debugging purposes and assuming you control the code I think it would be easier to just define a logical option which turns on or off debugging as shown below. Below we turn it on or use options(debug = NULL) or options(debug = FALSE) to turn it off.

  options(debug = TRUE)

  for (j in letters[1:2]) {
    cat(j)
    for (i in 1:2) {
      cat(i, "\n")
      if (getOption("debug", FALSE)) break
    }
  }

CodePudding user response:

Thanks to the @g-grothendieck English rephrasing, I have found the solution here.

I still don't understand why I cannot do that directly. Anyway: that's it; there, you can find a solution.

Thank you all!

  • Related