0

I want to create a class of results, say things. The main function makeThings returns (actually a list) with the class things addded (all these details are given in code below).

In addition to the method print, which should be the default method to display things, I want another method called explain which would print things with more information.

How can I create the second method, and make sure that it is sent to NAMESPACE using roxygen tags as this is to be put in a CRAN-compatible package. I believe S3 object-oriented approach is fine for my purpose.

A MWE:

#' @title makeThings is the main function
#' 
#' @description
#' This is what this function does.
#' 
#' @export
makeThings <- function(x) {
    res <- list(A=1:10, B=40:50)
    class(res) <- "things"
    return(res) 
}

#' @title print is the default method for things
#' 
#' @description
#' print outputs using a very basic format
#' 
#' @export
print.things <- function( something, ...) {print(something$A)}

#' @title explain is another, more verbosed, method for showing things.
#' 
#' @description
#' use explain( makeThings(43) ) to have more details.
#' 
#' @method explain things
#' @export
explain.things <- function( something, ...) {print("The meaning is ...")}

Now, as it stands, print and explain are sent as S3method to NAMESPACE, but typing ? explain indicates that explain is in the generic environment, not in my package environment. Also, typing the instruction

explain(makeThings(3))

returns the error Error in explain(makeThings(3)) : could not find function "explain". Some explanations appreciated as I tried many variations with no luck so far.

As far as possible, I would like to have these three functions in the same file.

Denis Cousineau
  • 311
  • 4
  • 16
  • 1) To get help you need the full name: `?explain.things`; 2) have you [exported the methods](https://stackoverflow.com/questions/18512528/how-to-export-s3-method-so-it-is-available-in-namespace)? – Rui Barradas Jul 28 '22 at 21:39
  • There is a standard generic function `print`, but there's no standard function `explain`. You would need to create that yourself; see the examples in section 5.1 of the R Language Definition manual. – user2554330 Jul 28 '22 at 21:44
  • @RuiBarradas: it has nothing to do with the question, so I'll edit it out. – user2554330 Jul 28 '22 at 21:45
  • @RuiBarradas so based on the link, I would have to both ``@export explain.things`` and ``@export``? Yes, that and the next comments both seems to do the trick. – Denis Cousineau Jul 28 '22 at 21:54
  • 1
    @user2554330 from section 5.1, I get that I must add ``explain <- function(x, ...) { UseMethod("explain") }`` so that I have a routing function? Does seems to work. Anyone wants to turn this into a response? – Denis Cousineau Jul 28 '22 at 21:55
  • I know what you should put in your `.R` code and in the `NAMESPACE`, but your question appears to be about doing this via `Roxygen2`, which I don't use (or recommend except in very limited circumstances), so it will have to be someone else. – user2554330 Jul 28 '22 at 22:49

1 Answers1

1

You want to have objects of a new class and have those objects processed by methods of generic functions.
To create a new generic you have to use UseMethod and it's a good idea to create a default method.

#' @title makeThings is the main function
#' 
#' @description
#' This is what this function does.
#' 
#' @export
makeThings <- function(x) {
  res <- list(A = 1:10, B = 40:50)
  class(res) <- "things"
  return(res) 
}

#' @title explain is another, more verbosed, method for showing things.
#' 
#' @description
#' use explain( makeThings(43) ) to have more details.
#' 
#' @details
#' This is the generic function
explain <- function(x, ...) UseMethod("explain")

#' @method explain default
#' @export
explain.default <- function(x, ...) print(x)

#' @method explain things
#' @export
explain.things <- function(x, ...) {print("The meaning is ...")}

#' @examples
explain("Hello, world!")
#> [1] "Hello, world!"
explain(makeThings(3))
#> [1] "The meaning is ..."

Created on 2022-07-28 by the reprex package (v2.0.1)


Then these functions should be exported from the package's namespace.
roxigen will write the following in the file NAMESPACE And with a message saying not to edit by hand.

S3method(explain, things)
export(explain)
export(makeThings)
Rui Barradas
  • 70,273
  • 8
  • 34
  • 66