Skip to content

How to debug reference classes?

6 messages · andre zege, John Chambers, Mark Bravington

#
How do you debug methods of a reference class? I've been using mtrace, which
is excellent, but i cannot figure out how to mtrace a reference class
method. Maybe there is some other way to debug these, for example with
ordinary trace? for now i am only able to use options(error=recover), which
is not giving me idea where exactly in the code i am once i am stopped on an
error. 

--
View this message in context: http://r.789695.n4.nabble.com/How-to-debug-reference-classes-tp3434269p3434269.html
Sent from the R devel mailing list archive at Nabble.com.
#
This is a good wish-list item.  The natural mechanism would be a version 
of the standard trace() function as a reference method with the same 
arguments as the current trace(), minus those that make no sense.  So:
    xx$trace(edit, browser)
for example, to trace execution of the reference method "edit" defined 
in the class of xx.  The mechanism does not exist now, and will require 
some modifications or extensions to the existing trace() implementation.

Meanwhile, the following slightly ugly workaround seems to apply trace() 
to a reference method.  Here, xx is the object created in the example 
for ReferenceClasses, with method $edit().  [Actually running the 
example removes the class definition, so this was done from a copy of 
the source code for the example.]

The steps in the workaround:

- make a copy of the method,
   edit <- xx$edit

- arrange to trace it in xx:
   trace(edit, browser, where = xx)
(this produces a note and a warning, but they seem harmless)

- remove the copy (just to be safe)
   rm(edit)

- now run things with whatever trace action you speficied.

- if needed after debugging, untrace() the method.
   untrace("edit", where = xx)

An example is below.

Of course, one could also just define xx$edit to call a regular 
function, say myEdit() and trace that.  But the workaround doesn't 
require changing the existing definition.

Suggestions for a better or less ugly workaround are welcome.  I'll look 
at fixing up a trace() method for 2.13.1

John

==============================
 > edit <- xx$edit
 > trace(edit, browser, where = xx)
Constructing traceable class "refMethodDefWithTrace"
Environment of class "refMethodDef" is locked; using global environment 
for new class
Tracing function "edit" in package "2011-04-07 14:34:43"
[1] "edit"
Warning message:
In getPackageName(whereF) :
   Created a package name, "2011-04-07 14:34:43", when none found
 > rm(edit)
 > xx$edit(1,2,3)
Tracing xx$edit(1, 2, 3) on entry
Called from: eval(expr, envir, enclos)
Browse[1]> objects()
[1] "i"     "j"     "value"
Browse[1]> j
[1] 2
Browse[1]> j <- 3
Browse[1]>
 > xx$data
      [,1] [,2] [,3]
[1,]    1    5    3
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12
 > untrace("edit", where = xx)
Untracing function "edit" in package "2011-04-07 14:34:43"
 > xx$edit(1,2,-1)
 > xx$data
      [,1] [,2] [,3]
[1,]    1   -1    3
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

============================================
On 4/7/11 12:00 PM, A Zege wrote:
#
'mtrace' will work with reference classes, at least after an object is instantiated. I'm not familiar with the guts of reference classes, but the following quick experiment was successful.. If you run the example in '?ReferenceClasses' up to & including this line :

xx <- mEditor$new(data = xMat)

and then do this:

mtrace( edit, from=attr( xx, '.xData'))

and then run the next line of the example, which is

xx$edit(2, 2, 0)

then the debug window will come up as normal.

Now, what about if you want to mtrace 'edit' before objects are instantiated? Here the S4 structure defeated me temporarily, but I probably would have been able to beat it if I'd had more time... There are some notes on debugging S4 methods in 'package?debug' (note that '?mtrace' itself is out-of-date on S4-- I have gotten S4 debugging to work, but it's only described in 'package?debug') and that might be enough to get you going.

HTH

Mark ('debug' package author)

Mark Bravington
CSIRO CMIS
Marine Lab
Hobart
Australia
#
Good to know.  However, _please_ don't use the horrible kludge in the 
attr(..) expression.  From my experimenting, it worked fine just to say:

mtrace(edit, from = xx)

and even if that did not work, from = as.environment(xx) is identical in 
effect to the attr() expression and means something.  (Usually the 
coercion to "environment" happens automatically.)

The attr() expression is strongly deprecated and very much not 
guaranteed to work.  First, it's discouraged to use the .xData slot, 
which is part of the implementation and not part of the API.  And ditto 
to access _any_ slot by attr(), for the same reason.

However, in my experimenting the technique required xx$edit to have been 
evaluated at some point before the call to mtrace(). Reference methods 
are copied to the object when first required (for efficiency).  Because 
my workaround explicitly used xx$edit, the problem didn't arise.  Just 
evaluating xx$edit should be enough.

On the "before instantiated" point.  I assume you mean in order to trace 
the method in all objects generated from the reference class.  I had 
thought about that too.  The same mechanism I described in my previous 
mail works for this as well, but requires a kludge to get the 
environment containing the methods.  The steps I outlined are as before 
but modified (in the example) as follows:

 > mm =  mEditor$def at refMethods
 > edit = mm$edit
 > trace(edit, browser, where = mm)

(mm is the environment with the methods).  Then the objects generated by 
mEditor$new() will have the traced version.

The same technique didn't seem to work for mtrace(), but a modification 
might.

John
On 4/7/11 4:56 PM, Mark.Bravington at csiro.au wrote:
#
Righto, thanks-- got it. When it comes to debugging, I'm no purist-- the 'debug' package has to work thru all sorts of undocumented "features" in R, so those of a sensitive disposition are advised _never_ to look at its internal code!

Seems like the following works for mtracing refclass methods (based on completely inadequate experimentation, though):

To 'mtrace' a refclass method 'edit' in a particular object 'xx', after 'xx' has been created:

xx$edit <- xx$edit # a "force"; JC's point that methods are . I will sort this out in 'mtrace' eventually
mtrace( edit, from=xx) # now eg xx$edit( 1, 1, 99) will launch debugger
mtrace( edit, from=xx, FALSE) # to clear the mtrace-- mtrace.off won't work properly here

To 'mtrace' all subsequent invocations of a method 'edit' in class 'mEditor', in whatever objects of class 'mEditor' subsequently get created:

mtrace( edit, from=mEditor$def at refMethods)
# now eg xx <- mEditor$new( data=xMat); xx$edit( 5, 5, 99) will launch debugger
mtrace( edit, from=mEditor$def at refMethods, FALSE) # to clear the mtrace

bye
Mark

Mark Bravington
CSIRO CMIS
Marine Lab
Hobart
Australia
#
Thank you very much, gentlemen. It seems reference classes will make my life
much easier. I won't pretend that i fully understand the wizardry with
environments that you do, but it works :). Namely the steps to mtrace a
class method by doing what John and Mark outlined
   xx$edit<-xx$edit
   mtrace(edit, from=xx)
   xx$edit(1,1,99)

do the magic of starting mtrace which solves my problem for practical
purposes. I was not able to make the second part of prescription related to
debugging unconstructed objects work. Namely, whenever i do 

 mtrace( edit, from=mEditor$def at refMethods) 

I get 
Error in parent.env(from) : the empty environment has no parent. Must be
doing something wrong, but haven't yet figured what.

--
View this message in context: http://r.789695.n4.nabble.com/How-to-debug-reference-classes-tp3434269p3436674.html
Sent from the R devel mailing list archive at Nabble.com.