2

I would like to make the log function a generic so that I can alter it's behavior under some newclass.

I have a minimal package with a DESCRIPTION file:

Package: logmethod
Type: Package
Title: A new Log Method
Version: 0.1
Date: 2017-03-23
Author: Me
Maintainer: Who to complain to <yourfault@somewhere.net>
Description: More about what it does (maybe more than one line)
License: MIT
LazyData: TRUE
RoxygenNote: 5.0.1

And the R Code, based on what I've learned at Writing R Extensions and Is it bad style to redefine non-S3 base functions as S3 functions in an R package?

#' @name log_method
#' @title A New Log Method
#'
#' @description A new \code{log} method
#'
#' @param x a numeric, complex, or measured variable
#' @param base a positive or complex measured variable: the base with respect to which
#'   logarithms are computed. Defaults to \emph{e}=\code{exp(1)}.
#' @param ... Additional arguments to pass to other methods.
#'
#' @export

log <- function(x, base, ...)
{
  UseMethod("log")
}

#' @rdname log_method
#' @export

log.default <- function(x, base, ...)
{
  base::log(x, base)
}

#' @rdname log_method
#' @export

log.newclass <- function(x, base, ...)
{
  print("See, it dispatched")
  log.default(as.numeric(x), as.numeric(base), ...)
}

When I run check, I keep getting the warning

  • checking S3 generic/method consistency ... WARNING Warning: declared S3 method 'log.default' not found Warning: declared S3 method 'log.newclass' not found See section 'Generic functions and methods' in the 'Writing R Extensions' manual.

When I install the package, I'm able to use log.default and log.newclass, so I'm not sure how to interpret this warning that the methods are not found. Turning an R S3 ordinary function into a generic describes how to make an S4 function, but I'd like to stick to S3 if possible. I would love to know why I keep getting this warning.

EDIT:

The NAMESPACE might also be useful.

# Generated by roxygen2: do not edit by hand

S3method(log,default)
S3method(log,newclass)
export(log)
Community
  • 1
  • 1
Benjamin
  • 16,897
  • 6
  • 45
  • 65

1 Answers1

1

It turns out the piece of the puzzle I was missing is that log and most of its cousins are already generic. From the ?log documentation details

All except logb are generic functions: methods can be defined for them individually or via the Math group generic.

Thus, the proper coding for the new methods would have been the following (notice the lack of a UseMethod call)

log.default <- function(x, base, ...)
{
  base::log(x, base)
}

log.newclass <- function(x, base, ...)
{
  print("See, it dispatched")
  log.default(as.numeric(x), as.numeric(base), ...)
}

On the other hand, since logb is not defined as a generic, that is a case where the instructions in Writing R Extensions would have been relevant (because dispatch is not yet designed)

logb <- function(x, base, ...)
{
  UseMethod("logb")
}

logb.default <- function(x, base, ...)
{
  base::logb(x, base)
}

logb.newclass <- function(x, base, ...)
{
  print("See, it dispatched")
  logb.default(as.numeric(x), as.numeric(base), ...)
}

So if you're coming across an warning like in the question, it may be worth checking into whether or not the base version of the function isn't already a generic.

Benjamin
  • 16,897
  • 6
  • 45
  • 65