When debugging a function, I would like to move up to the parent frame and look at some variables there. How do I do this?
Here is a sample:
f <- fun
Just call on.exit(browser())
when browsing f
's body and you'll return back to it after you're done with g()
See output copied from the console below :
> f <- function() {
+ x <-1
+ g(x+1)
+ }
> g <- function(z) {
+ y = z+2
+ return(y)
+ }
> debug("f")
> debug("g")
> f()
debugging in: f()
debug at #1: {
x <- 1
g(x + 1)
}
Browse[2]> on.exit(browser()) # browser() will be run in this environment just before we exit
Browse[2]>
debug at #2: x <- 1
Browse[2]>
debug at #3: g(x + 1)
Browse[2]>
debugging in: g(x + 1)
debug at #1: {
y = z + 2
return(y)
}
Browse[3]>
debug at #2: y = z + 2
Browse[3]>
debug at #3: return(y)
Browse[3]>
exiting from: g(x + 1)
Browse[2]> x # we're back to f so we can investigate x
[1] 1
Browse[2]>
exiting from: f()
[1] 4
You can use recover
(it is often used to debug code after an actual error,
via options(error=utils::recover)
,
but it can be called directly).
> f()
debugging in: g(x + 1)
debug at #1: {
y = z + 2
return(y)
}
Browse[2]> ls()
[1] "z"
Browse[2]> recover()
Enter a frame number, or 0 to exit
1: f()
2: #3: g(x + 1)
Selection: 1
Called from: top level
Browse[3]> ls()
[1] "x"
Browse[3]> x
[1] 1
Browse[3]>
In R terminology, you are wanting to investigate the parent frame of g()
's evaluation environment (i.e. the environment in which g
was called). The functions for doing that are documented in the help page for ?sys.parent
.
Once your browser indicates that you are 'debugging in g(x + 1)'
, you can do the following. (Thanks to Joshua Ulrich for suggesting where
to help locate ones position in the call stack .)
# Confirm that you are where you think you are
where
# where 1 at #3: g(x + 1)
# where 2: f()
# Get a reference to g()'s parent frame (an environment object)
pframe <- parent.frame()
pframe
# <environment: 0x019b9174>
# Examine the contents of the parent frame
ls(env=pframe)
# [1] "x"
# Get the value of 'x' in the parent frame
get("x", env = pframe)
# [1] 1
EDIT: To understand the collection of functions described in ?sys.parent
, it's probably worth noting that parent.frame()
is (basically) shorthand for sys.frame(sys.parent(1))
. If you find yourself in an evaluation environment farther down a call stack (as revealed by where
, for instance), you can reach into environments farther back up the call stack (say two steps up) by either parent.frame(2)
or sys.frame(sys.parent(2))
.