Internal S3 generics with an lapply
Asked Answered
T

1

6

I have an S3 generic function that I would like to be an internal part of a package. I would prefer not to export it if possible. An interesting downside of this is that it seems that lapply is unable to find or use the proper S3 method. Does anyone know the reason behind this behavior? below is a reproducible example which involves installing a dummy package from my github.

In this case, the generic function is docheck which will return TRUE if the object is "foo" and FALSE otherwise.

library(remotes)
install_github("jtlandis/SOExample")
#> Skipping install of 'SOExample' from a github remote, the SHA1 (27ab918c) has not changed since last install.
#>   Use `force = TRUE` to force installation
library(SOExample)

The foo function is just an NA object with the "foo" class.

foo
#> function () 
#> structure(NA, class = "foo")
#> <bytecode: 0x0000000015033878>
#> <environment: namespace:SOExample>

fun_success() just shows a case in which the internal (not exported) S3 function works.

fun_success
#> function (x) 
#> {
#>     docheck(x)
#> }
#> <bytecode: 0x0000000013f83100>
#> <environment: namespace:SOExample>

fun_success(foo())
#> [1] TRUE

fun_failure() calls the same internal generic method, but fails

fun_failure
#> function (x) 
#> {
#>     lapply(list(x), docheck)
#> }
#> <bytecode: 0x0000000015e68df0>
#> <environment: namespace:SOExample>

fun_failure(foo())
#> Error in UseMethod("docheck"): no applicable method for 'docheck' applied to an object of class "foo"

Created on 2021-07-24 by the reprex package (v2.0.0)

Thermometer answered 25/7, 2021 at 2:33 Comment(0)
A
5

R has been getting more picky about making sure S3 methods are properly registered. The normal method to register package generic methods is with the S3method() in the NAMESPACE file. But if you are trying to keep all of docheck unexported, then you'll need to register the S3 method yourself. You can do that with the .S3method() function. In your R file, add this line

# Existing line...
# docheck.foo <- function(x) T
# New line...
.S3method("docheck", "foo", docheck.foo)

This will allow the lapply to find the method.

Astyanax answered 25/7, 2021 at 4:47 Comment(1)
I appreciate the answer, and will apply it in my package since it fixes the issue. Still seems like a lot of extra work tbh. There isn't yet a good explanation to why lapply is unable to find the proper method. Maybe lapply evaluates in a new environment?Thermometer

© 2022 - 2025 — McMap. All rights reserved.