[Roxygen-devel] Parsing roxgen blocks

Vitalie Spinu spinuvit at gmail.com
Wed Aug 29 15:43:25 CEST 2012


  >> Hadley Wickham <hadley at rice.edu>
  >> on Wed, 29 Aug 2012 08:16:07 -0500 wrote:

  > [splitting out into separate emails instead of one huge one]
  >> Not that difficult,  S4 always leave traces in the evaluation
  >> environment, objects starting with:
  >> 
  >> methods:::.TableMetaPattern()
  >> [1] "^[.]__T__"
  >> methods:::.ClassMetaPattern()
  >> [1] "^[.]__C__"
  >> 
  >> Inspecting those, you know exactly what was installed.

  > Yeah, that's the easy part ;)  Now how do you find which comment block
  > they were associated with?

  > As far as I can see, there's no other way to do this apart from
  > parsing the call.  I also don't see another way to document user
  > created functions that modify the global state - e.g. add_roccer in
  > roxygen3 (this wouldn't be necessary if we used S4, but the principle
  > remains).

  HW> Could you flesh out this example a bit more?  I don't understand why
  HW> you'd want to document objects that aren't evaluated by the user.
  >> 
  >> Ah sorry, that was stupid. I meant
  >> 
  >> eval({ a <- generate_object_a()
  >> b <- generate_object_b()})
  >> 
  >> Roxygen can make a convention if two declarations are followed
  >> imidiately after each over they souled be documented in the same
  >> roxy-doc and same Rd file:
  >> 
  >> foo <- function(a) ..
  >> boo <- function(a) ..
  >> 
  >> will put both foo and boo in the same file. Curently one needs two
  >> documentation blocks and rdname tag if I am not mistaken.

  > Again, the challenge is to connect the objects to the roxygen block.
  > Without parsing the call, how do you know that the comment block
  > should be attached to a and b?

  > One option would be to evaluate each source block as you encounter it.
  > That would resolve the problem above (and would make it possible to do
  > `my_class <- setClass` and still know that it was creating a class).
  > The problem is that the S4 functions don't seem to be very good at
  > returning what they're created:

Precisely what I had in mind (I was convinced that roxygen is already
doing that and didn't bother to explain).

Each code chunk should be evaluated in a new environment. Then
environment is inspected and all the new objects/classes/methods are
returned.

There might be an environment (or list) in roxygen namespace holding all
the object guessers (roxy_env_inspectors?). Each of them is called and
should return a list of new objects detected.

The basic one just looks for normally assigned objects,
roxy_env_inspector.S3 looks for S3 tables *in* the evaluation
environment, roxy_env_inspector.S4_classes looks in class table and gets
the classes defined, roxy_env_inspector.S4_methods searches the S4
table. 

If a package declares some wiredo side effect initialization (which is
pretty rare) it should define roxy_env_inspector.Wierdo_thing and add it
to roxy_env_inspectors environment (which should not be sealed in the
package).

  >> a <- setMethod("plot", "numeric", function(x, ...) {})
  >> str(a)
  >  chr "plot"

  > Which means you'd have to compare states of all the S4 class/method
  > tables before and after each call.  That seems slow and error prone to
  > me.

Each call to meta functions setClass, setMethod etc creates a table *in*
the evaluation env, if it is a top environment (environment should be
explicitly designated as a top environment for this to work). 

Indeed, as far as I can remember, S4 methods an generics are also copied
to the central table for efficiency, but roxygen need not care about
those, local tables are enough.

  > If you wanted to write some code to do it, I'd definitely be happy to
  > consider it, but given that my current system works, I'm not in a big
  > hurry to rewrite it.

Ok, I will wrap up a proof-of-the-concept code.

   Vitalie


More information about the Roxygen-devel mailing list