1

I would like to have the following generic function, which

  1. checks for thew allowedFormats (This works),
  2. than executes the generic function base on the type of argument x (works)
  3. evaluates the statements after the call of UseMethod() (does not work - as expected)

Now it states in the help for UseMethod

Any statements after the call to UseMethod will not be evaluated as UseMethod does not return.

So this is not surprising. But is there a way that I can achieve this, apart from defining an additional function validate_after() which calls validate() followed by cat(“Validation completed”)?

validate <- function (
  x,
  allowedFormats
) {

  # Check arguments ---------------------------------------------------------

  allowedFormats <- c("none", "html", "pdf", "word", "all")
  if (!(report %in% allowedFormats)) {
    stop("'report' has to be one of the following values: ", allowedFormats)
  }

  UseMethod("validate", x)

  cat(“Validation completed”)
}

Rainer
  • 8,347
  • 1
  • 23
  • 28

2 Answers2

1

Define and call a nested generic

> validate <- function (x, allowedFormats) {
+     .validate <- function(x, allowedFormats) {
+         UseMethod("validate", x)
+     }
+     # Check arguments ---------------------------------------------------------
+     # ...
+     .validate(x, allowedFormats)
+     cat("Validation completed")
+ }
> validate.numeric <- function(x, allowedFormats) {
+     cat('Working...\n')
+ }
> validate(5, NA)
Working...
Validation completed
Dmitry Zotikov
  • 2,133
  • 15
  • 12
0

Depending on what you wish to achieve this might be feasible using the 'on.exit' command, as demonstrated below:

test <- function(x, ...){
    if(!is.integer(x))
        stop("wups")
    on.exit(cat("'On exit' executes after UseMethod, but before the value is returned. x = ", x,"\n"))
    UseMethod("test")
}
test.integer <- function(x, ...){
    cat("hello i am in a function\n")
    x <- x + 3
    cat("I am done calculating. x + 3 = ",x,"\n")
    return(x)
}
test(1:3)

hello i am in a function
I am done calculating. x + 3 =  4 5 6 
'On exit' executes after UseMethod, but before the value is returned. x =  1 2 3 
[1] 4 5 6

This is not necessarily a perfect solution. For example if one wished to perform some extra calculations on the methods result, the result is not propagated to the the generic function (as UseMethod does not return). A possible workaround could be to force feed a environment into the called method, to store results in.

Oliver
  • 8,169
  • 3
  • 15
  • 37
  • Good idea. But I think for my purpose (to render a validation report afterwards), the best solution might be to use a different function. – Rainer May 22 '19 at 11:15
  • Indeed i would suggest the same. If you were to release it as a package, it would also be simpler for others to expand upon your package, if the generic function is using common standards. Most packages validate within the method body. – Oliver May 22 '19 at 16:20