[Rd] debuggingState() analogous to tracingState() ?

Duncan Murdoch murdoch.duncan at gmail.com
Thu Oct 2 18:07:59 CEST 2014


On 02/10/2014 11:55 AM, Richard M. Heiberger wrote:
> Interesting timing.  I could have used this additional control
> yesterday in class.
>
> I am teaching a graduate Statistical Computing class.  Last night I
> went through the symbolic deriviatives (the deriv and D functions) in
> Section 9.6 of the Blue Book.  The D function is recursive.  I
> illustrated its behavior with debug(D) and then studied the statement
>      D(expression(x^2+4), "x")
>
> At each step the console displays the entire switch() statement.  And
> inside ESS the entire switch statement in the derivative.R buffer is
> highlighted.  That is too much redundancy.  I would like to have the
> .R buffer highlighted and maybe a truncated version of the statement
> displayed in the *R* (console) buffer.  I am thinking of a trunctation
> similar to what C-c C-c in ESS does when it sends over a function
> definition.  Somewhere around the third or fourth level of recursion I
> would truncate it even further.  When investigating
>     3*x^2 + 4*x^5
> It would be nice to see the detail of several levels of recursion for
> the 3*x^2 term and turn off the debug/trace behavior of the 4*x^5
> term, with the debug/trace beahvior automatically coming back on when
> the two terms are merged.
>
>
> I discovered I would like an additional stop during debug.
>
> Here is a simple function to illustrate.
>
> simple <- function(x) {
>     y <- x + x
>     2*y
> }
>
> debug stops before the 'y <- x+x 'and again before the '2*y' is
> evaluated and I can do regular browser investigations.  When I hit
> enter, I want it to stop again after 2*y has been evaluated and before
> it returns to the console.
You can add on.exit(browser()) to do that, or use the exit option of 
trace().  The new (R-devel only) function returnValue() will tell you 
what is about to be returned.  In the current release, the return value 
isn't available at that point.

Duncan Murdoch

> I would like to investigate the result and
> then go back and investigate the intermediate variables with the
> result in view.  Obviously I can redefine my own function to
>
> redesignedsimple <- function(x) {
>     y <- x + x
>     z <- 2*y
>     z
> }
>
> but doing that to a function inside a NAMESPACE is very difficult to
> get right.
>
>
> Rich
>
> On Thu, Oct 2, 2014 at 10:55 AM, Martin Maechler
> <maechler at stat.math.ethz.ch> wrote:
> > We have had some conversation within R core,
> > lead by Duncan Murdoch and me, about a proposal
> > to extend  the current  tracingState() functionality
> > by something tentatively called debuggingState().
> >
> > Duncan has allowed me to copy the previous conversation
> > (after very minor editing):
> >
> > The following is quite technical and assumes you know more about
> > R's debug()ing and trace()ing than an estimated 99.9% of the R users:
> >
> >>>>>> Duncan Murdoch <murdoch.duncan at gmail.com>
> >>>>>>     on Thu, 2 Oct 2014 07:19:34 -0400 writes:
> >
> >  > On 02/10/2014, 6:36 AM, Martin Maechler wrote:
> >  >>>>>>> Duncan Murdoch <murdoch.duncan at gmail.com>
> >  >>>>>>> on Thu, 2 Oct 2014 05:41:00 -0400 writes:
> >  >>
> >  >> > On 02/10/2014, 5:17 AM, Martin Maechler wrote:
> >  >> >>>>>>> Martin Maechler <maechler at stat.math.ethz.ch>
> >  >> >>>>>>> on Sat, 27 Sep 2014 22:55:21 +0200 writes:
> >  >> >>
> >  >> >> > It would be really nice to temporarily disable debugging similar to
> >  >> >> > tracingState() being able to turn of trace()ing.
> >  >> >>
> >  >> >> > In eval.c  the corresponding C code would be used as the  tracingState()
> >  >> >> > analogue is used.
> >  >> >>
> >  >> >> > [...........]
> >  >> >> > ???
> >  >> >>
> >  >> >> It seems to work ok, the few cases I've tried.
> >  >> >>
> >  >> >> I wonder a bit about the R / C interface.
> >  >> >> Using an extra function  debuggingState() seems a bit of a
> >  >> >> waste, and I was thinking of enhancing
> >  >> >> tracingState() from a 1-argument to a 2-argument form.
> >  >> >>
> >  >> >> something like
> >  >> >>
> >  >> >> tracingState <- function(on = NULL, debug = on)
> >  >> >>         .Internal(traceOnOff(on, debug))
> >  >> >>
> >  >> >> but I don't see how to keep usages such as
> >  >> >>
> >  >> >>   on <- tracingState(FALSE)       # turn it off QUICKLY (via a .Internal)
> >  >> >>   if(on) {
> >  >> >>     on.exit(tracingState(TRUE)) # restore on exit, keep off during trace
> >  >> >>     ............
> >  >> >>   }
> >  >> >>
> >  >> >> working back compatibly.
> >  >> >>
> >  >> >> We could think of tracingState() only returning length one when
> >  >> >> called with one argument, and returning length two when called
> >  >> >> with a second argument... but that seems messy.
> >  >> >>
> >  >> >> If nobody has a better idea, I'd commit a new   debuggingState()
> >  >> >> function which is very much "parallel" to  tracingState().
> >  >>
> >  >> > It's hard to comment on this, because I don't know exactly what
> >  >> > behaviour is controlled by the debugging flag.
> >  >>
> >  >> Good point.  The flag, accessed via RDEBUG(.), is used in quite a few places,
> >  >> and the intent and my experiments have replaced
> >  >>
> >  >>      RDEBUG(.)
> >  >> by   RDEBUG(.) && R_current_debug_state()
> >  >>
> >  >> in some places, but not in most places.
> >  >>
> >  >> > Will it cause an
> >  >> > explicit call to browser() to be a no-op, or does it just control breaks
> >  >> > triggered by entry into a function that has been marked by debug()?
> >  >>
> >  >> What would you want?  Probably the latter, right?
> >  >> With my use case below, however, I could argue I'd even want  browser()
> >  >> to be a no-op in that case.  It is not so important to me.
> >  >>
> >  >> > What is the effect of a call to a function marked with debugOnce()?
> >  >>
> >  >> Good question.  Here my code was such that the function would also
> >  >> not have been debugged.
> >  >> But of course, that is open for "debate",  and I am glad you've
> >  >> started / continued the discussion.
> >  >>
> >  >> My main use case for
> >  >>         debuggingState(FALSE)
> >  >>
> >  >> would be when I want to call some R function that  "just runs
> >  >> through" and gives me its result, even though the user may have
> >  >> added the debug flag to a very basic R function which is called
> >  >> by my R function.
> >  >>
> >  >> Given these question, you could start arguing we'd want more
> >  >> than just  TRUE or FALSE for debugging state,
> >  >> just so one could apply differing behaviour in the above cases.
> >
> >  > Or the alternative:  expand the use of the tracingState() flag to affect
> >  > RDEBUG as well.
> >
> > Indeed.  If we additionally want to remain backcompatible, I think,
> > we'd need to add new values in addition to {TRUE, FALSE} (and
> > NULL for input).
> >
> > E.g., --- making up something to be improved ---
> > using bit patterns which when added give an integer "tracing+debugging-state"
> >
> > 1 : tracing-turned-off
> > 2 : debugging turned off, allowing browser() and debugonce()
> > 4 : making browser()   a no-op
> > 8 : making debugonce() a no-op
> >
> > and hence 1+2+4+8 = 15 turns off all "browsing/debugging"
> > for which I'd typically want a convenient short cut.
> >
> > for back compatibility,
> > FALSE = 1
> > TRUE  = 0
> >
> > I'd use UI with a vector of character strings, that can be
> > translated to integer codes entirely analogous to
> > .deparseOpts()   {used from deparse(), dput() and dump()}.
> >
> > -----
> >
> > A considerably simpler interface which would be good enough for
> > my use, was to simply add a new  debuggingState() function with
> > TRUE/FALSE option, and we would just have to decide how much
> > "turning off debugging" should happen when the state is set to FALSE.
> > In that case, I would still like the ability (on the level of R)
> > to simultaneously turn off debugging and tracing and turn them
> > back on as easily.  So I'd consider setting up debuggingState()
> > in a way that it can simultaneously turn off and on both tracing
> > and debugging.
> >
> >  > I don't have much of an opinion on these questions.  I've never used the
> >  > tracingState() function, though I use trace() all the time (via
> >  > setBreakpoint()).  You might want to consult people who write debugger
> >  > front-ends.
> >
> > which I am now doing: I'm including ESS-core,
> > Jonathan (RStudio) and Tobias (StatET) which Duncan mentioned as
> > being interested and having asked for better debugging support
> > functionality in the past, such as
> >
> >  > the ability to add a breakpoint to a function that is
> >  > currently being evaluated.
> >
> > So, after quite a bit of musing, we are grateful for your
> > thoughtful comments on this
> > (and yes: I am fan of  "keep it simple!"  and  "small is beautiful!"
> >  also inside R's code base).
> >
> > Martin Maechler,
> > ETH Zurich
> >
> > _______________________________________________
> > ESS-core list: https://stat.ethz.ch/mailman/listinfo/ess-core



More information about the R-devel mailing list