[Roxygen-devel] S4 implementation of @usage

Hadley Wickham hadley at rice.edu
Thu Aug 30 22:07:37 CEST 2012


On Thu, Aug 30, 2012 at 2:12 PM, Vitalie Spinu <spinuvit at gmail.com> wrote:
>   >> Hadley Wickham <hadley at rice.edu>
>   >> on Thu, 30 Aug 2012 11:29:07 -0500 wrote:
>
>
>   >> So roxygenize will iterate 3 times over all tags and call prepareTag on
>   >> first iteration, then prepareDoc, and finally preparePackage.
>
>   > That's better, but generally you only need to call preparePackage
>   > once, not once for each instance of that tag.
>
> No, no ... that was precisely the main point! It should process each
> *tag* at "package level". Then process each *tag* at a "block level" and
> finally at "tag level". Here is the complete pseudo code for roxy
> package:

Hmmmm, that's an interesting approach.

I had another idea, and that was that what I was calling a GlobalTag
is originally what I was calling a Roccer - i.e. it's something that
takes a RoxyPackage as input and a RoxyPackage as output.  Then it
would be a clean separation: RoxyTags act locally (at the RoxyBlock
level) and Roccers act globally (at the RoxyPackage level).

I think it makes sense to make this distinction because the process
you outline below doesn't quite fit the common Roccer (e.g. family,
inheritParams, include) scenario which typically involves two passes:
the first to built up a datastructure that stores information about
the global structure, and the second that goes through and modifies
individual RocBlocks.

I also think it seems wrong to have a generic called procPackage - why
do you have the name of the class it operates on in the generic name?

>   roxygenise <- function(...., ## see below for explanation
>                          processors = c(procRd, procNamespace, procCollate, procMyCoolIndex)){
>     roxypkg <- parse_all_files(...)
>
>     roxypkg <- procPackage(roxypkg)
>
>     for ( proc in processors )
>       roxypkg <- proc(roxypkg)
>
>   }

I was thinking of something like

roxygenise <- function(..., tags, roccers, outputs) {

  pkg <- roxy_init(...)  # not an S4 method because it starts the ball rolling
  pkg <- roxyProcess(pkg, tags)
  pkg <- roxyProcess(pkg, roccers)
  roxyWrite(pkg, outputs)
}

where if not specified tags, roccers and outputs would default to
finding all classes that inherited from the appropriate base class.

>   > I don't think that can work, because combining Rd commands can't work
>   > at the string level, and it varies from command to command.  i.e. if
>   > you have multiple @keywords you do
>
>   > \keyword{one}
>   > \keyword{two}
>   > \keyword{three}
>
>   > but for multiple @params you do
>
>   > \arguments{
>   > \item{one}{desc one}
>   > \item{two}{desc two}
>   > }
>
> Good example. Let me fit it into the above paradigm.
>
> After the *block level* processing this RoxyBlock will have a tag of
> class "TagArguments" (and *no* tags of class TagParam). That is, it is a
> *standalone* entity which can be transformed by outRd into a string.
>
> In other words, TagParam's roxyProcess *block level* method creates a tag
> @arguments and removes the corresponding TagParam argument from the
> roxyBlock object.

Problems:

* calling it "block" level doesn't really make sense because it's now
(potentially) working on multiple blocks

* what happens to the objects? Does each RoxyBlock now have a list of
objects associated with it? If so, how do you associate the usage
statements with the objects.  i.e. how would you resolve:

#' Topic a.
#'
#' @rdname shared
a <- function(x) {}

#' Topic b.
#'
#' @rdname shared
#' @usage b() # some comment here
b <- function(x) {}


>   > If you did it with different methods (outRd, outNamespace,
>   > outDescription), and the user created a new type of output (e.g.
>   > outDemoIndex) how would they tell roxygen to all call the outDemoIndex
>   > on every block/tag?
>
> Good point. I think your solution of passing processing functions to
> roxygenize should work best:
>
>   roxygenize( ..., output = c(outRd, outCollate, outNamespace, outDemoIndex))
>
> where outRd, outCollate, outDemoIndex are function *or* generics which
> roxygenize will call on the RoxyPackage object. First procPackage
> should be called, and then all the "outputers" in turn. All of them
> should return back an object of class RoxyPackage which will be passed
> to the next processor in the chain.
>
> BTW, why "output"? I find this name confusing. This functions can have
> arbitrary side effects, or just change the content of the RoxyPackage
> object.

That's an interesting observation - the output objects have basically
the same semantics as the roccer objects. But I think there are some
important differences:

* Output objects are used solely for their side effects (writing to
disk).  They return nothing.

* Roccer objects return a modified RoxyPackage and have no
side-effects.  This is important for testing.

* All roccers need to be run before output can occur.

>   > But output does differ between tags?  Some need to output Rd, some
>   > NAMESPACE, etc.
>
> BTW, is it a tag task to generate namespace? Isn't it that RoxyDoc's method
> should generate it.

It's the tags task to say where it's output should go - it shouldn't
modify the file on disk, but it should provide the output in suitable
format for writing.

>   > Hmmm, but you list rd, html and text as potential output formats - I
>   > definitely don't see html and text as output types.  That's something
>   > you might generate from the Rd files, but I don't think it's the job
>   > of roxygen to generate anything that R doesn't use directly.  Maybe
>   > that's why we seem to be talking past each other.
>
> You are right. I am confused. And my confusion stems from the "output"
> terminology which I have hard time to get used to.  Somehow it really
> doesn't sound right to call a namespace generator, an output. outCollate
> is even more weird.

I think of it as an output in the same sense that the RoxyBlocks (or
RoxyPackage) are inputs - everything else is just an intermediate
form.  The user only sees what the Output objects do.

Hadley

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


More information about the Roxygen-devel mailing list