Skip to content

Instantly share code, notes, and snippets.

@jmbarbone
Created October 5, 2024 01:38
Show Gist options
  • Save jmbarbone/482120c9b5ce2d319ca11d6e245935c6 to your computer and use it in GitHub Desktop.
Save jmbarbone/482120c9b5ce2d319ca11d6e245935c6 to your computer and use it in GitHub Desktop.
playing around with some type setting for R functions
library(S7)
typed <- function(fun, ...) {
  ..params <- list(...)
  ..syms <- names(..params)
  stopifnot(..syms %in% names(formals(fun)))
  
  # should make this a function
  ..validator <- S7::new_class("..validator", properties = ..params)

  # todo include a return -- something executed on.exit()

  ..ugh <- substitute(
    do.call(
      ..validator,
      as.list(match.call())[intersect(names(as.list(match.call())), ..syms)]
    ),
    environment()
  )

  body(fun) <- as.call(c(`{`, ..ugh, as.list(body(fun))))
  fun
}

foo <- function(a = 1, b = 2) {
  return(a + b)
}

foo(a = 1)
#> [1] 3
bar <- typed(
  foo,
  a = class_integer,
  b = class_integer
)
bar(a = 1L)
#> [1] 3
try(bar(a = 1.0))
#> Error : <..validator> object properties are invalid:
#> - @a must be <integer>, not <double>
try(bar(a = Sys.Date()))
#> Error : <..validator> object properties are invalid:
#> - @a must be <integer>, not S3<Date>

Created on 2024-10-04 with reprex v2.1.1

@jmbarbone
Copy link
Author

Wait, this could be good:

typed <- function(...) {
  eval(substitute(alist(...)))
}

typed(
  a = 1 ~ class_numeric | class_double,
  b = TRUE ~ class_logical,
  a + 1
)
#> $a
#> 1 ~ class_numeric | class_double
#> 
#> $b
#> TRUE ~ class_logical
#> 
#> [[3]]
#> a + 1

Created on 2025-03-04 with reprex v2.1.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment