jcubic
jcubic

Reputation: 66488

How to show stack trace without error in R?

In JavaScript I can use console.log(new Error().stack) or console.trace() to show stack trace.

Is there something like this in R? Can I show functions call stacktrace in my position. I have complex application and it's hard to follow the code where what is called, showing stacktrace where function is called would simplify finding how code is executed.

I've tried this hack:

foo <- function() bar()
bar <- function() {
  tryCatch(
    stop('NOP'),
    error = function(e) {
      print(traceback(e))
  })
}
foo()

but it don't work I would need to catch the error at top level to see that stack. Is there simple function that will show stack frames when called?

EDIT: Here is example how this look like in JavaScript, this how I want this to work, is similar thing possible in R?

function foo() {
  bar();
}
function bar() {
  baz();
}
function baz() {
  // console.trace is dev tools function
  // this will show up the stack if open dev tools and then run the snippet
  console.trace();
  console.log(new Error().stack);
}
foo();

As you can see the error is not thrown, it just creates an object and browser will add the stack trace of the calls to that object, so it can be inspected.

Upvotes: 3

Views: 1083

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 173793

If you want to see the call stack without an error being thrown, you could try something like this:

show_stack <- function() {
  cat("#----- Stack containing call to show_stack -----#\n\n")
  x <- sys.calls()
  lapply(head(x, -1), function(x) {print(x); cat("\n")})
  cat("#-----------------------------------------------#\n\n")
}

Which you just insert in whichever function you want to trace:

foo <- function() bar()
bar <- function() baz()
baz <- function() show_stack()

Resulting in:

foo()
#> #----- Stack containing call to show_stack -----#
#> 
#> foo()
#> 
#> function() bar()
#> 
#> function() baz()
#> 
#> #-----------------------------------------------#

Or, for a more real-world example:

my_mean <- function(x) {
  show_stack()
  sum(x)/length(x)
}

Which may be run multiple times in a call:

tapply(iris$Sepal.Length, iris$Species, my_mean)
#> #----- Stack containing call to show_stack -----#
#> 
#> tapply(iris$Sepal.Length, iris$Species, my_mean)
#> 
#> lapply(X = ans[index], FUN = FUN, ...)
#> 
#> FUN(X[[i]], ...)
#> 
#> #-----------------------------------------------#
#> 
#> #----- Stack containing call to show_stack -----#
#> 
#> tapply(iris$Sepal.Length, iris$Species, my_mean)
#> 
#> lapply(X = ans[index], FUN = FUN, ...)
#> 
#> FUN(X[[i]], ...)
#> 
#> #-----------------------------------------------#
#> 
#> #----- Stack containing call to show_stack -----#
#> 
#> tapply(iris$Sepal.Length, iris$Species, my_mean)
#> 
#> lapply(X = ans[index], FUN = FUN, ...)
#> 
#> FUN(X[[i]], ...)
#> 
#> #-----------------------------------------------#
#> 
#>     setosa versicolor  virginica 
#>      5.006      5.936      6.588 

Upvotes: 5

Related Questions