I have a generic function called foo
. It operates differently on the classes bar
and baz
but there is some shared pre-processing that needs to only be done once. What is the idiomatic R way of carrying this out?
In my silly example below, I want to multiply the object being passed to the generic by 10. Yet when the method is called, the original value is printed to the console. I have read the language definition and know that the below pattern does not work. My question is: Where or how should I handle shared processing of generic arguments before calling the method?
a <- structure(1:5, class="bar")
b <- structure(6:10, class="baz")
foo <- function(x) {
x <- x * 10 # where should shared preprocessing go?
UseMethod("foo")
}
foo.bar <- function(x) {
cat("Foo!", x)
}
foo.baz <- function(x) {
cat("Baz!", x)
}
# does not propagate the operations carried out `foo`
foo(a)
foo(b)
1) Layer foo on top of actual generic Change
foo
to perform the preliminary code and invokefoo_
a new generic as shown. Renamefoo.bar
andfoo.baz
tofoo_.bar
andfoo_.baz
respectively so that we are left with (have also added newlines to the example):Now test it out:
For an example of this in a widely used package see the source of dplyr::mutate
2) NextMethod Another way would be to give every object a class vector of two classes with
"foo"
made a subclass of"bar"
in the case ofa
and of"baz"
in the case ofb
. Then useNextMethod
. Solution (1) seems simpler and it may seem weird that"foo"
is a subclass of both"bar"
and"baz"
but here is an example of this one just in case:Test it noting that we have changed the definitions of
a
andb
so that they work with this approach: