diff --git a/R/function.R b/R/function.R index 8e4d8e0..425a5bb 100644 --- a/R/function.R +++ b/R/function.R @@ -63,6 +63,14 @@ ts_result <- function(type, value) { #' @param result return type (ignored if overloads are provided) #' @export #' @md +#' +#' @return a ts function object which has a `call` method that will call the function with the given arguments, which will be checked for type correctness. +#' +#' @examples +#' f <- ts_function(function(x = ts_integer(1), y = ts_character(1)) { +#' x + nchar(y) +#' }, result = ts_integer(1)) +#' f$call(1, "hello") ts_function <- function(f, ..., result = ts_void()) { args <- list(...) if (!is.null(result) && !is_ts_object(result)) { @@ -117,9 +125,19 @@ print.ts_function <- function(x, ...) { #' Anything that is not a function simply returns itself. #' However, functions are wrapped with `Rserve::ocap()`, #' and the result is subsequently wrapped with `ts_app()`. +#' #' @param x A ts function object (`ts_function()`) #' @export #' @md +#' +#' @returns An object of class 'OCref', see [Rserve::ocap()] +#' +#' @examples +#' f <- ts_function(function(x = ts_integer(1), y = ts_character(1)) { +#' x + nchar(y) +#' }, result = ts_integer(1)) +#' app <- ts_app(f) # class of 'OCref' +#' # this can now be used in an Rserve application, for example ts_app <- function(x) UseMethod("ts_app") #' @export diff --git a/R/types.R b/R/types.R index 4605d54..d539ca7 100644 --- a/R/types.R +++ b/R/types.R @@ -1,4 +1,4 @@ -#' Typed object +#' Typed object (internal use only) #' #' This is the base type for all typed objects, and can be used to define #' custom types. @@ -115,9 +115,11 @@ check_type.ts_function <- function(type, x) { #' Union type #' #' Create a union of types. Currently this only accepts schemas as strings. -#' @param ... Types to merge +#' @param ... Zod types to merge (as strings) #' @export #' @md +#' @examples +#' x <- ts_union("z.number()", "z.string()") ts_union <- function(...) sprintf("z.union([%s])", paste(..., sep = ", ")) ts_array <- function(type = c("z.number()", "z.boolean()", "z.string()")) { @@ -157,6 +159,7 @@ n_type_fun <- function(n, type) { #' x$check(TRUE) #' #' \dontrun{ +#' # this will fail #' x$check(5) #' } ts_logical <- function(n = -1L) { @@ -182,6 +185,14 @@ ts_logical <- function(n = -1L) { #' @return A ts object that accepts integer scalars or vectors of length `n`. #' @export #' @md +#' @examples +#' x <- ts_integer(1) +#' x$check(1L) +#' +#' \dontrun{ +#' # this will fail +#' x$check(1:10) +#' } ts_integer <- function(n = -1L) { ts_object( n_type(n, "z.number()", "z.instanceof(Int32Array)"), @@ -209,6 +220,15 @@ ts_integer <- function(n = -1L) { #' @return A ts object that accepts numeric scalars or vectors of length `n`. #' @export #' @md +#' @examples +#' x <- ts_numeric(1) +#' x$check(1) +#' +#' \dontrun{ +#' # this will fail +#' x$check(c(1, 2, 3)) +#' x$check("a") +#' } ts_numeric <- function(n = -1L) { ts_object( n_type(n, "z.number()"), @@ -231,6 +251,9 @@ ts_numeric <- function(n = -1L) { #' @return A ts object that accepts strings or string vectors of length `n`. #' @export #' @md +#' @examples +#' x <- ts_character(1) +#' x$check("a") ts_character <- function(n = -1L) { ts_object( n_type(n, "z.string()"), @@ -256,6 +279,15 @@ vector_as_ts_array <- function(x) { #' #' @export #' @md +#' @examples +#' x <- ts_factor(levels = c("a", "b")) +#' x$check(factor("a", levels = c("a", "b"))) +#' +#' \dontrun{ +#' # this will fail +#' x$check("a") +#' x$check(factor("c", levels = c("a", "b", "c"))) +#' } ts_factor <- function(levels = NULL) { ts_object( ifelse(is.null(levels), @@ -290,6 +322,10 @@ ts_factor <- function(levels = NULL) { #' #' @export #' @md +#' +#' @examples +#' x <- ts_list(a = ts_integer(1), b = ts_character(1)) +#' x$check(list(a = 1L, b = "a")) ts_list <- function(...) { values <- list(...) @@ -348,6 +384,10 @@ ts_list <- function(...) { #' #' @export #' @md +#' +#' @examples +#' x <- ts_dataframe(a = ts_integer(1), b = ts_character(1)) +#' x$check(data.frame(a = 1L, b = "a")) ts_dataframe <- function(...) { values <- list(...) type <- "z.record(z.string(), z.any())" @@ -379,11 +419,15 @@ ts_dataframe <- function(...) { #' Null type #' -#' This is a type that only accepts `NULL`. +#' This is a type that only accepts `NULL`. For function return types, use `ts_void`. #' #' @return A ts object that only accepts `NULL`. #' @export #' +#' @md +#' @examples +#' x <- ts_null() +#' x$check(NULL) ts_null <- function() { ts_object( "z.null()", @@ -402,6 +446,7 @@ ts_null <- function() { #' @return A ts object that accepts `NULL`. #' @export #' @md +#' @seealso \code{\link{ts_null}} ts_void <- function() { ts_object( "z.void()", diff --git a/man/ts_app.Rd b/man/ts_app.Rd index 3cf8c66..9addebe 100644 --- a/man/ts_app.Rd +++ b/man/ts_app.Rd @@ -9,8 +9,18 @@ ts_app(x) \arguments{ \item{x}{A ts function object (\code{ts_function()})} } +\value{ +An object of class 'OCref', see \code{\link[Rserve:ocap]{Rserve::ocap()}} +} \description{ Anything that is not a function simply returns itself. However, functions are wrapped with \code{Rserve::ocap()}, and the result is subsequently wrapped with \code{ts_app()}. } +\examples{ +f <- ts_function(function(x = ts_integer(1), y = ts_character(1)) { + x + nchar(y) +}, result = ts_integer(1)) +app <- ts_app(f) # class of 'OCref' +# this can now be used in an Rserve application, for example +} diff --git a/man/ts_character.Rd b/man/ts_character.Rd index f18322f..425f35b 100644 --- a/man/ts_character.Rd +++ b/man/ts_character.Rd @@ -16,3 +16,7 @@ A ts object that accepts strings or string vectors of length \code{n}. Strings are represented in Zod schema as either a string (\code{z.string()}), or a string array (\code{z.array(z.string())}). } +\examples{ +x <- ts_character(1) +x$check("a") +} diff --git a/man/ts_dataframe.Rd b/man/ts_dataframe.Rd index eef97b1..d9a895a 100644 --- a/man/ts_dataframe.Rd +++ b/man/ts_dataframe.Rd @@ -15,3 +15,7 @@ A ts object that accepts data frames with the specified types. \description{ This is essentially a list, but the elements must have names and are all the same length. } +\examples{ +x <- ts_dataframe(a = ts_integer(1), b = ts_character(1)) +x$check(data.frame(a = 1L, b = "a")) +} diff --git a/man/ts_factor.Rd b/man/ts_factor.Rd index eedbf24..c18e54e 100644 --- a/man/ts_factor.Rd +++ b/man/ts_factor.Rd @@ -15,3 +15,13 @@ A ts object that accepts factors with the specified levels. \description{ Factors are integers with labels. On the JS side, these are \emph{always} represented as a string array (even if only one value - yay!). } +\examples{ +x <- ts_factor(levels = c("a", "b")) +x$check(factor("a", levels = c("a", "b"))) + +\dontrun{ +# this will fail +x$check("a") +x$check(factor("c", levels = c("a", "b", "c"))) +} +} diff --git a/man/ts_function.Rd b/man/ts_function.Rd index cfc890f..c76e353 100644 --- a/man/ts_function.Rd +++ b/man/ts_function.Rd @@ -29,3 +29,9 @@ can explicitly be defined with their types as formal arguments: \if{html}{\out{