Skip to content

Instantly share code, notes, and snippets.

@moodymudskipper
Created December 31, 2020 13:00
Show Gist options
  • Save moodymudskipper/7f6fb1acd5808a6dc84d207cae5ed0a7 to your computer and use it in GitHub Desktop.
Save moodymudskipper/7f6fb1acd5808a6dc84d207cae5ed0a7 to your computer and use it in GitHub Desktop.
`for` <- function(it, seq, expr) {
if(!identical(substitute(it), quote(.))) {
tryCatch(
eval.parent(substitute(base::`for`(it, seq, expr))),
error = function(e) {stop(c("In `for`: ", e$message), call. = FALSE)})
return(invisible())
}
l <- length(seq[[1]])
nms1 <- names(seq)
nms2 <- paste0("*", names(seq), "*")
names(seq) <- nms2
e <- new.env(parent = parent.frame())
list2env(seq, e)
expr0 <- as.call(c(quote(`{`), parse(text=sprintf("%s <- `%s`[[`*i*`]]", nms1, nms2))))
code <- bquote(splice = TRUE, {
on.exit({
rm(list = ls(pattern = "^\\*.*\\*$"))
list2env(as.list(environment()), parent.env(environment()))
})
for (`*i*` in 1:.(l)) {
.(expr0)
.(substitute(expr))
}
})
tryCatch(
eval(envir = e, code),
error = function(e) {stop(c("In `for`: ", e$message), call. = FALSE)})
}
# works as before
for(i in 1:3) print(i^2)
# use dot for multiple iterators
for(. in list(a=1:3, b=3:5)) {
print(a*b)
}
# just like original for, we keep values defined in loop, errors are slightly different
for(. in list(a=1:3, b=3:5)) {
y <- a*b
print(y)
if(y==8) stop("!!!")
}
# defined values are in current environment
y
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment