some docs
This commit is contained in:
parent
8f62f4d85f
commit
350808a8e2
18
R/function.R
18
R/function.R
@ -63,6 +63,14 @@ ts_result <- function(type, value) {
|
|||||||
#' @param result return type (ignored if overloads are provided)
|
#' @param result return type (ignored if overloads are provided)
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @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()) {
|
ts_function <- function(f, ..., result = ts_void()) {
|
||||||
args <- list(...)
|
args <- list(...)
|
||||||
if (!is.null(result) && !is_ts_object(result)) {
|
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.
|
#' Anything that is not a function simply returns itself.
|
||||||
#' However, functions are wrapped with `Rserve::ocap()`,
|
#' However, functions are wrapped with `Rserve::ocap()`,
|
||||||
#' and the result is subsequently wrapped with `ts_app()`.
|
#' and the result is subsequently wrapped with `ts_app()`.
|
||||||
|
#'
|
||||||
#' @param x A ts function object (`ts_function()`)
|
#' @param x A ts function object (`ts_function()`)
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @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")
|
ts_app <- function(x) UseMethod("ts_app")
|
||||||
|
|
||||||
#' @export
|
#' @export
|
||||||
|
|||||||
51
R/types.R
51
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
|
#' This is the base type for all typed objects, and can be used to define
|
||||||
#' custom types.
|
#' custom types.
|
||||||
@ -115,9 +115,11 @@ check_type.ts_function <- function(type, x) {
|
|||||||
#' Union type
|
#' Union type
|
||||||
#'
|
#'
|
||||||
#' Create a union of types. Currently this only accepts schemas as strings.
|
#' Create a union of types. Currently this only accepts schemas as strings.
|
||||||
#' @param ... Types to merge
|
#' @param ... Zod types to merge (as strings)
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @md
|
||||||
|
#' @examples
|
||||||
|
#' x <- ts_union("z.number()", "z.string()")
|
||||||
ts_union <- function(...) sprintf("z.union([%s])", paste(..., sep = ", "))
|
ts_union <- function(...) sprintf("z.union([%s])", paste(..., sep = ", "))
|
||||||
|
|
||||||
ts_array <- function(type = c("z.number()", "z.boolean()", "z.string()")) {
|
ts_array <- function(type = c("z.number()", "z.boolean()", "z.string()")) {
|
||||||
@ -157,6 +159,7 @@ n_type_fun <- function(n, type) {
|
|||||||
#' x$check(TRUE)
|
#' x$check(TRUE)
|
||||||
#'
|
#'
|
||||||
#' \dontrun{
|
#' \dontrun{
|
||||||
|
#' # this will fail
|
||||||
#' x$check(5)
|
#' x$check(5)
|
||||||
#' }
|
#' }
|
||||||
ts_logical <- function(n = -1L) {
|
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`.
|
#' @return A ts object that accepts integer scalars or vectors of length `n`.
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @md
|
||||||
|
#' @examples
|
||||||
|
#' x <- ts_integer(1)
|
||||||
|
#' x$check(1L)
|
||||||
|
#'
|
||||||
|
#' \dontrun{
|
||||||
|
#' # this will fail
|
||||||
|
#' x$check(1:10)
|
||||||
|
#' }
|
||||||
ts_integer <- function(n = -1L) {
|
ts_integer <- function(n = -1L) {
|
||||||
ts_object(
|
ts_object(
|
||||||
n_type(n, "z.number()", "z.instanceof(Int32Array)"),
|
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`.
|
#' @return A ts object that accepts numeric scalars or vectors of length `n`.
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @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_numeric <- function(n = -1L) {
|
||||||
ts_object(
|
ts_object(
|
||||||
n_type(n, "z.number()"),
|
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`.
|
#' @return A ts object that accepts strings or string vectors of length `n`.
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @md
|
||||||
|
#' @examples
|
||||||
|
#' x <- ts_character(1)
|
||||||
|
#' x$check("a")
|
||||||
ts_character <- function(n = -1L) {
|
ts_character <- function(n = -1L) {
|
||||||
ts_object(
|
ts_object(
|
||||||
n_type(n, "z.string()"),
|
n_type(n, "z.string()"),
|
||||||
@ -256,6 +279,15 @@ vector_as_ts_array <- function(x) {
|
|||||||
#'
|
#'
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @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_factor <- function(levels = NULL) {
|
||||||
ts_object(
|
ts_object(
|
||||||
ifelse(is.null(levels),
|
ifelse(is.null(levels),
|
||||||
@ -290,6 +322,10 @@ ts_factor <- function(levels = NULL) {
|
|||||||
#'
|
#'
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @md
|
||||||
|
#'
|
||||||
|
#' @examples
|
||||||
|
#' x <- ts_list(a = ts_integer(1), b = ts_character(1))
|
||||||
|
#' x$check(list(a = 1L, b = "a"))
|
||||||
ts_list <- function(...) {
|
ts_list <- function(...) {
|
||||||
values <- list(...)
|
values <- list(...)
|
||||||
|
|
||||||
@ -348,6 +384,10 @@ ts_list <- function(...) {
|
|||||||
#'
|
#'
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @md
|
||||||
|
#'
|
||||||
|
#' @examples
|
||||||
|
#' x <- ts_dataframe(a = ts_integer(1), b = ts_character(1))
|
||||||
|
#' x$check(data.frame(a = 1L, b = "a"))
|
||||||
ts_dataframe <- function(...) {
|
ts_dataframe <- function(...) {
|
||||||
values <- list(...)
|
values <- list(...)
|
||||||
type <- "z.record(z.string(), z.any())"
|
type <- "z.record(z.string(), z.any())"
|
||||||
@ -379,11 +419,15 @@ ts_dataframe <- function(...) {
|
|||||||
|
|
||||||
#' Null type
|
#' 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`.
|
#' @return A ts object that only accepts `NULL`.
|
||||||
#' @export
|
#' @export
|
||||||
#'
|
#'
|
||||||
|
#' @md
|
||||||
|
#' @examples
|
||||||
|
#' x <- ts_null()
|
||||||
|
#' x$check(NULL)
|
||||||
ts_null <- function() {
|
ts_null <- function() {
|
||||||
ts_object(
|
ts_object(
|
||||||
"z.null()",
|
"z.null()",
|
||||||
@ -402,6 +446,7 @@ ts_null <- function() {
|
|||||||
#' @return A ts object that accepts `NULL`.
|
#' @return A ts object that accepts `NULL`.
|
||||||
#' @export
|
#' @export
|
||||||
#' @md
|
#' @md
|
||||||
|
#' @seealso \code{\link{ts_null}}
|
||||||
ts_void <- function() {
|
ts_void <- function() {
|
||||||
ts_object(
|
ts_object(
|
||||||
"z.void()",
|
"z.void()",
|
||||||
|
|||||||
@ -9,8 +9,18 @@ ts_app(x)
|
|||||||
\arguments{
|
\arguments{
|
||||||
\item{x}{A ts function object (\code{ts_function()})}
|
\item{x}{A ts function object (\code{ts_function()})}
|
||||||
}
|
}
|
||||||
|
\value{
|
||||||
|
An object of class 'OCref', see \code{\link[Rserve:ocap]{Rserve::ocap()}}
|
||||||
|
}
|
||||||
\description{
|
\description{
|
||||||
Anything that is not a function simply returns itself.
|
Anything that is not a function simply returns itself.
|
||||||
However, functions are wrapped with \code{Rserve::ocap()},
|
However, functions are wrapped with \code{Rserve::ocap()},
|
||||||
and the result is subsequently wrapped with \code{ts_app()}.
|
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
|
||||||
|
}
|
||||||
|
|||||||
@ -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()}),
|
Strings are represented in Zod schema as either a string (\code{z.string()}),
|
||||||
or a string array (\code{z.array(z.string())}).
|
or a string array (\code{z.array(z.string())}).
|
||||||
}
|
}
|
||||||
|
\examples{
|
||||||
|
x <- ts_character(1)
|
||||||
|
x$check("a")
|
||||||
|
}
|
||||||
|
|||||||
@ -15,3 +15,7 @@ A ts object that accepts data frames with the specified types.
|
|||||||
\description{
|
\description{
|
||||||
This is essentially a list, but the elements must have names and are all the same length.
|
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"))
|
||||||
|
}
|
||||||
|
|||||||
@ -15,3 +15,13 @@ A ts object that accepts factors with the specified levels.
|
|||||||
\description{
|
\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!).
|
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")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -29,3 +29,9 @@ can explicitly be defined with their types as formal arguments:
|
|||||||
\if{html}{\out{<div class="sourceCode">}}\preformatted{ts_function(function(x = ts_integer(), y = ts_string()) \{ ... \})
|
\if{html}{\out{<div class="sourceCode">}}\preformatted{ts_function(function(x = ts_integer(), y = ts_string()) \{ ... \})
|
||||||
}\if{html}{\out{</div>}}
|
}\if{html}{\out{</div>}}
|
||||||
}
|
}
|
||||||
|
\examples{
|
||||||
|
f <- ts_function(function(x = ts_integer(1), y = ts_character(1)) {
|
||||||
|
x + nchar(y)
|
||||||
|
}, result = ts_integer(1))
|
||||||
|
f$call(1, "hello")
|
||||||
|
}
|
||||||
|
|||||||
@ -16,3 +16,12 @@ A ts object that accepts integer scalars or vectors of length \code{n}.
|
|||||||
Integers are represented in Zod schema as either a number (\code{z.number()}),
|
Integers are represented in Zod schema as either a number (\code{z.number()}),
|
||||||
or a Int32Array (\code{z.instanceof(Int32Array)}).
|
or a Int32Array (\code{z.instanceof(Int32Array)}).
|
||||||
}
|
}
|
||||||
|
\examples{
|
||||||
|
x <- ts_integer(1)
|
||||||
|
x$check(1L)
|
||||||
|
|
||||||
|
\dontrun{
|
||||||
|
# this will fail
|
||||||
|
x$check(1:10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -15,3 +15,7 @@ A ts object that accepts lists with the specified types.
|
|||||||
\description{
|
\description{
|
||||||
A list is a vector of other robjects, which may or may not be named.
|
A list is a vector of other robjects, which may or may not be named.
|
||||||
}
|
}
|
||||||
|
\examples{
|
||||||
|
x <- ts_list(a = ts_integer(1), b = ts_character(1))
|
||||||
|
x$check(list(a = 1L, b = "a"))
|
||||||
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ x <- ts_logical(1)
|
|||||||
x$check(TRUE)
|
x$check(TRUE)
|
||||||
|
|
||||||
\dontrun{
|
\dontrun{
|
||||||
|
# this will fail
|
||||||
x$check(5)
|
x$check(5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,5 +10,9 @@ ts_null()
|
|||||||
A ts object that only accepts \code{NULL}.
|
A ts object that only accepts \code{NULL}.
|
||||||
}
|
}
|
||||||
\description{
|
\description{
|
||||||
This is a type that only accepts \code{NULL}.
|
This is a type that only accepts \code{NULL}. For function return types, use \code{ts_void}.
|
||||||
|
}
|
||||||
|
\examples{
|
||||||
|
x <- ts_null()
|
||||||
|
x$check(NULL)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,3 +16,13 @@ A ts object that accepts numeric scalars or vectors of length \code{n}.
|
|||||||
Numbers are represented in Zod schema as either a number (\code{z.number()}),
|
Numbers are represented in Zod schema as either a number (\code{z.number()}),
|
||||||
or a Float64Array (\code{z.instanceof(Float64Array)}).
|
or a Float64Array (\code{z.instanceof(Float64Array)}).
|
||||||
}
|
}
|
||||||
|
\examples{
|
||||||
|
x <- ts_numeric(1)
|
||||||
|
x$check(1)
|
||||||
|
|
||||||
|
\dontrun{
|
||||||
|
# this will fail
|
||||||
|
x$check(c(1, 2, 3))
|
||||||
|
x$check("a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\alias{is_ts_object}
|
\alias{is_ts_object}
|
||||||
\alias{get_type}
|
\alias{get_type}
|
||||||
\alias{check_type}
|
\alias{check_type}
|
||||||
\title{Typed object}
|
\title{Typed object (internal use only)}
|
||||||
\usage{
|
\usage{
|
||||||
ts_object(
|
ts_object(
|
||||||
input_type = "any",
|
input_type = "any",
|
||||||
|
|||||||
@ -7,8 +7,11 @@
|
|||||||
ts_union(...)
|
ts_union(...)
|
||||||
}
|
}
|
||||||
\arguments{
|
\arguments{
|
||||||
\item{...}{Types to merge}
|
\item{...}{Zod types to merge (as strings)}
|
||||||
}
|
}
|
||||||
\description{
|
\description{
|
||||||
Create a union of types. Currently this only accepts schemas as strings.
|
Create a union of types. Currently this only accepts schemas as strings.
|
||||||
}
|
}
|
||||||
|
\examples{
|
||||||
|
x <- ts_union("z.number()", "z.string()")
|
||||||
|
}
|
||||||
|
|||||||
@ -13,3 +13,6 @@ A ts object that accepts \code{NULL}.
|
|||||||
This is a type that accepts null values (this would typically be used for
|
This is a type that accepts null values (this would typically be used for
|
||||||
functions that return nothing).
|
functions that return nothing).
|
||||||
}
|
}
|
||||||
|
\seealso{
|
||||||
|
\code{\link{ts_null}}
|
||||||
|
}
|
||||||
|
|||||||
30
tests/testthat/test-custom-types.R
Normal file
30
tests/testthat/test-custom-types.R
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
hist_type <- ts_object(
|
||||||
|
input_type = "z.object({
|
||||||
|
breaks: z.array(z.number()),
|
||||||
|
counts: z.array(z.number()),
|
||||||
|
density: z.array(z.number()),
|
||||||
|
mids: z.array(z.number()),
|
||||||
|
xname: z.string(),
|
||||||
|
equidist: z.boolean(),
|
||||||
|
})",
|
||||||
|
return_type = "Robj.list({
|
||||||
|
breaks: Robj.numeric(),
|
||||||
|
counts: Robj.numeric(),
|
||||||
|
density: Robj.numeric(),
|
||||||
|
mids: Robj.numeric(),
|
||||||
|
xname: Robj.character(1),
|
||||||
|
equidist: Robj.logical(1),
|
||||||
|
})",
|
||||||
|
check = function(x) {
|
||||||
|
stopifnot(is.list(x))
|
||||||
|
stopifnot(all(c("breaks", "counts", "density", "mids", "xname", "equidist") %in% names(x)))
|
||||||
|
stopifnot(is.numeric(x$breaks))
|
||||||
|
stopifnot(is.numeric(x$counts))
|
||||||
|
stopifnot(is.numeric(x$density))
|
||||||
|
stopifnot(is.numeric(x$mids))
|
||||||
|
stopifnot(is.character(x$xname))
|
||||||
|
stopifnot(is.logical(x$equidist))
|
||||||
|
stopifnot(isTRUE(all.equal(length(x$breaks), length(x$counts), length(x$density), length(x$mids))))
|
||||||
|
x
|
||||||
|
}
|
||||||
|
)
|
||||||
Loading…
x
Reference in New Issue
Block a user