[Roxygen-devel] S4 implementation of @usage

Hadley Wickham hadley at rice.edu
Thu Aug 30 15:57:41 CEST 2012


> I have done my best here https://gist.github.com/3516476

Thanks - that's useful. A few comments/questions:

* I don't think the spec for processTag is quite right yet - currently
you have it returning a transformed object of the same class as the
input - but that only works for a limited number of tags.  Many tags
also need to modify other tags the rocblock.  For example the "@intro"
tag (a virtual tag added to the start of every rocblock) needs to
modify the title, description and details. The @docType tag needs to
modify a lot of other pieces.

 It would be possible to rewrite them to "pull" rather than "push",
i.e. so that @title would check @intro, and @keywords would check
@docType but I don't think that's as good a design as it means the
code for one tag needs to be put in multiple places.

* Similarly, I still don't see how tags that operate globally would
work. I think that's partly because the model is so focussed on the
individual tag - the tag classes become very heavy - that's where all
the logic is stored.  That's not such a good fit for actions that work
on multiple tags in multiple rocblocks.  I wonder if we need a
alternative model for some tags - instead of being stored in each
rocblock, they should be stored globally:

setClass("GlobalTag", contains = "Tag",
  slots = "RocBlock" # pointer back to the rocblock that contained them
)
setClass("FamilyTag", contains = "GlobalTag")
setClass("IncludeTag", contains = "GlobalTag")
setClass("InheritParamsTag", contains = "GlobalTag")

# Takes list of tags as input (not sure how dispatch would work) and
rocBlocks as input
# Returns list of rocblocks as output
setGeneric("processGlobalTags")

* I think I need to explain the output model a little bit more - the
output needs to be by tag, and return an intermediate representation
of the output object. More like:

setGeneric("outRd")
setMethod("outRd", "roxyTag", function(tag, rocblock)) {
  filename <- getTag(rocblock, "rdname")
  rdCommand(tag at name, tag at value, path = filename)
}

This is because the output methods can't write directly to disk - they
may need to do some aggregation:

* multiple rocblocks may output to the same Rd file with @rdname
* all outputs to NAMESPACE need to be sorted and have duplicates removed.

Another possible approach could be:

setClass("OutputRd")
setGeneric("makeOutput", function(input, output) {})
setMethod("makeOutput", c("TagParam", "OutputRd"), ...)
setMethod("makeOutput", c("TagImport", "OutputNamespace"), ...)
setMethod("makeOutput", c("TagIncludes", "OutputDescription") ...)

setMethod("makeOutput", c("RoxyBlock", "Output"), function(input, output) {
  lapply(input at tags, makeOutput, output = output)
}
setMethod("makeOutput", c("RoxyPackage", "Output"), function(input, ouput) {
  unlist(lapply(input at blocks, makeOutput, output = output), recursive = FALSE)
}

setGeneric("writeOutput", function(output, data) {})
setMethod("writeOutput", c("outputNamespace", "list")) {
  lines <- sort(unique(unlist(data)))
  write_if_different(lines, "NAMESPACE")
}

That would make it easier for the user to specify which sorts of
output they want because they could just provide a list of Output
objects to roxygenise.


>   > Object seems a bit awkward because it's part of the rocblock, and is
>   > currently stored in a list with it's value and it's name. But I don't
>   > see how you'd dispatch on it, unless you pull it out into a separate
>   > argument.
>
> Yes, dispatch is on the object which is part of rocblock (maybe
> roxyBlock?). roxyParse is used only internally, so not a big deal. When
> iterating, disassembling and calling roxyParse(rblock at object), rblock at doc)
> looks fine to me.

I think it would still need to be rblock at object@value, but that's ok too.

Hadley

-- 
Assistant Professor
Department of Statistics / Rice University
http://had.co.nz/


More information about the Roxygen-devel mailing list