R/doWhile.R

Defines functions doWhile

Documented in doWhile

#' @title doWhile
#' @param do     Expression to evaluate at least once. The "do" expression will be repeated until the "While" condition is FALSE.
#' @param While  Logical expression indicating the stopping condition. The doWhile loop will end when the "While" condition is no longer TRUE. Default is FALSE (execute "do" expression once and then return).
#' @param Return Expression to evaluate and return (allows returning of variables scoped inside the doWhile function). Default is NULL.
#' @param vars   List of variables to pass by value to the doWhile loop function.
#' @export
#' @examples
#'
#' doWhile(do={k=k+1; print(k)}, While={k<5},vars=list(k=0))
#' doWhile({if(!exists("k")) {k<-1} else {k<-k+1}; print(k)}, {k<5})
#'
#' k <<- 0
#' doWhile({k<<-k+1; print(k)}, {k<5})
#' rm(k)
#'
#' # Note that i remains zero here due to scoping
#' i=0
#' doWhile(do={i=i+1; print(i)}, While={i<10}, Return=i)
#' print(i)
#'
#' # But we can force an update of i using "i <<- i+1"
#' i=0
#' doWhile(do={i<<-i+1; print(i)}, While={i<10}, Return=i)
#' print(i)
#'
#' # or we can declare j (and jPI) in the scope of the doWhile:
#' jPI=doWhile(do={if(!exists("j")|!exists("jPI")){j<-0;jPI<-0}
#'                 else{j=j+1; jPI=jPI+pi}},
#'             While={j<10},
#'             Return={jPI})
#' print(jPI)
#'
#' # Using a list lets us check existence just once when we have many parameters in the loop:
#' Y = doWhile(do    ={ if(!exists("E")) {E<-list(x=pi, y=exp(1))}; E$y=E$x+E$y},
#'             While ={ E$y < 100},
#'             Return={ E$y})
#' print(Y)
doWhile <- function(do, While=F, Return=NULL, vars=NULL) {
  env = environment()
  if(!is.null(vars)) { list2env(vars, envir = env) }
    eval(substitute(do), env=env)
  while(eval(substitute(While), env=env)) {
    eval(substitute(do), env=env)
  }
  return(eval(substitute(Return), env=env))
}
mrparker909/doWhile documentation built on Nov. 4, 2019, 7:35 p.m.