Plan for debugging (and traceback)
I know there is the "transparent" plan, but I'm still not very helpful tracebacks:
library(future)
plan("transparent")
f = function(x) if (x > 5) stop("whoops") else x
g = function(x) f(x)
result %<-% g(10)
> Error in f(x) : whoops
> traceback()
17: stop(condition)
16: resignalCondition(future)
15: signalEarly(x, ...)
14: resolved.Future(future)
13: NextMethod()
12: resolved.UniprocessFuture(future)
11: resolved(future)
10: signalEarly(future, collect = FALSE)
9: run.UniprocessFuture(future)
8: run(future)
7: sequential(expr, envir = envir, substitute = FALSE, lazy = lazy,
seed = seed, globals = globals, local = local, earlySignal = earlySig
nal,
label = label, ...)
6: evaluator(expr, envir = envir, substitute = FALSE, lazy = lazy,
seed = seed, globals = globals, packages = packages, ...)
5: (function (expr, envir = parent.frame(), substitute = TRUE, globals = TRU
E,
packages = NULL, lazy = FALSE, seed = NULL, evaluator = plan("next"),
...)
{
if (substitute)
expr <- substitute(expr)
if (!is.function(evaluator)) {
stop("Argument 'evaluator' must be a function: ", typeof(evaluato
r))
}
future <- evaluator(expr, envir = envir, substitute = FALSE,
lazy = lazy, seed = seed, globals = globals, packages = packages,
...)
if (!inherits(future, "Future")) {
stop("Argument 'evaluator' specifies a function that does not ret
urn a Future object: ",
paste(sQuote(class(future)), collapse = ", "))
}
future
})(g(10), envir = <environment>, lazy = FALSE, seed = NULL, globals = TRU
E)
4: do.call(future::future, args = future.args, envir = assign.env)
3: futureAssign(name, expr, envir = envir, assign.env = assign.env,
substitute = FALSE)
2: futureAssignInternal(target, expr, envir = envir, substitute = FALSE)
1: result %<-% g(10)
-> I just get the top level call, nothing about f().
- Would it be possible to create a plan which just calls base R functions? E.g.,
futureCallcallsdo.call,futureAssigncallsassign,future_lapplycallslapply...? - Alternatively, would it be possible to store and query the traceback?
- Maybe there could also be a plan for the
evaluatepackage?
Sorry for the delay. Yes, the idea of the transparent backend is to simplify troubleshooting. It would be nice to have a barebone, minimal-overhead future backend for troubleshooting etc. Things like lazy evaluation (lazy = TRUE) makes this much complicated since we cannot just call eval() on the future expression immediately when the future is created. Having said that, I'll add it to the list of simplifying transparent, which currently just utilizes the sequential backend.
This is quite an old issue, but regarding FR 2, there's backtrace();
library(future)
plan(sequential)
f <- function(x) if (x > 5) stop("whoops") else x
g <- function(x) f(x)
result %<-% g(10)
which gives
> result
Error in f(x) : whoops
We can get a clean stack trace by calling backtrace() on this future/promise:
> backtrace(result)
[[1]]
result %<-% g(10)
[[2]]
futureAssignInternal(target, expr, envir = envir, substitute = FALSE)
[[3]]
futureAssign(name, expr, envir = envir, assign.env = assign.env,
substitute = FALSE)
[[4]]
do.call(future::future, args = future.args, envir = assign.env)
[[5]]
(function (expr, envir = parent.frame(), substitute = TRUE, lazy = FALSE,
seed = FALSE, globals = TRUE, packages = NULL, label = NULL,
gc = FALSE, ...)
{
if (substitute)
expr <- substitute(expr)
makeFuture <- plan("next")
future <- makeFuture(expr, substitute = FALSE, envir = envir,
lazy = lazy, seed = seed, globals = globals, packages = packages,
label = label, gc = gc, ...)
if (!inherits(future, "Future")) {
stop(FutureError("plan(\"next\") returned a function that does not return a Future object: ",
paste(sQuote(class(future)), collapse = ", ")))
}
future
})(g(10), envir = <environment>, lazy = FALSE, seed = NULL, globals = TRUE)
[[6]]
makeFuture(expr, substitute = FALSE, envir = envir, lazy = lazy,
seed = seed, globals = globals, packages = packages, label = label,
gc = gc, ...)
[[7]]
SequentialFuture(..., envir = envir)
[[8]]
UniprocessFuture(expr = expr, envir = envir, substitute = FALSE,
lazy = lazy, globals = globals, local = local, ...)
[[9]]
Future(expr = expr, substitute = FALSE, envir = envir, lazy = lazy,
asynchronous = FALSE, local = local, globals = globals, packages = packages,
...)
[[10]]
eval(quote(g(10)), new.env())
[[11]]
g(10)
[[12]]
function(x) f(x)
[[13]]
function(x) if (x > 5) stop("whoops") else x
[[14]]
f(x)