How to add to generic function print the message method print.message?

95 Views Asked by At

Suppose getwd() yields "C:/Users/Tom/Documents/Tom_Levers_Git_Repository".

In this repository, I have directory TomLeversRBox.

In this box, I have modules calculate_probability.R and print.message.R.

In the module calculate_probability.R, I have the following function.

box::use(./print.message)
box::use(stats[pnorm])

#' @export
calculate_probability <- function() {
    message <- paste("Probability: ", round(pnorm(1.644854, 0, 1, lower.tail = TRUE), 2), sep = "")
    class(message) <- "message"
    return(message)
}

In the module print.message.R, I have the following function.

#' @export
print.message <- function(message) {
    cat(message)
}

In RStudio's console, I run install.packages("box").

I run box::use(TomLeversRBox/calculate_probability[calculate_probability]).

I run calculate_probability().

I receive the following output.

[1] "Probability: 0.95"
attr(,"class")
[1] "message"

How do I add to generic function print the message method print.message, and print only Probability: 0.95?

I have also tried box::use(TomLeversRBox/calculate_probability[calculate_probability], TomLeversRBox/print.message[print.message]).

I strongly prefer to only use box::use(TomLeversRBox/calculate_probability[calculate_probability]).

1

There are 1 best solutions below

9
On BEST ANSWER

You need to use box::register_S3_method inside the module which defines the S3 method:

box::register_S3_method('print', 'message', print.message)

(And note that you don’t need to, nor should, export the method. It will be accessible anyway, as long as the module is loaded.)

This is required because there could be ambiguity between the names of different S3 generics, which is why ‘box’ does not try to figure this out by itself. To illustrate, consider the S3 method print.data.frame. Based on the name, we would probably assume that it would be a method overriding the generic print for the class data.frame. But it could also be a method overriding the generic print.data (if it is defined somewhere), for the S3 class frame.

Note that calling box::register_S3_method is only required when overriding generics that are imported from elsewhere (as is the case for print). For generics defined in the same module, there is no ambiguity, so ‘box’ figures out the required S3 definitions itself, e.g.:

# some/test.r

#' @export
myprint = function (x) UseMethod('myprint')

myprint.message = function (x) {
    cat('<message:', x, '>\n', sep = '')
}
box::use(
    some/test,
    TomLeversRBox/calculate_probabilities[calculate_probability],
)

test$myprint(calculate_probability())
# <message:Probability: 0.95>