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

Mark.Bravington at csiro.au Mark.Bravington at csiro.au
Fri Oct 3 00:14:28 CEST 2014


Just FYI: the 'debug' package lets you set a stop-before-exit, and of course the ability to adjust breakpoints while the function is running. You can get the current return value via 'get.retval()'.

There is some rough-edged support for debugging scripts, too.

Mark

Mark Bravington
CSIRO CMIS
Marine Lab
Hobart
Australia
________________________________________
From: r-devel-bounces at r-project.org [r-devel-bounces at r-project.org] on behalf of Richard M. Heiberger [rmh at temple.edu]
Sent: 03 October 2014 01:55
To: Martin Maechler
Cc: ESS-core; r-devel; Jonathan.McPherson.jonathan at rstudio.com
Subject: Re: [Rd] debuggingState() analogous to tracingState() ?

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.  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

______________________________________________
R-devel at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list