From 6f1646830569da122a91b20d51405d5ce6c11d45 Mon Sep 17 00:00:00 2001 From: Tom Elliott Date: Fri, 7 Feb 2025 13:16:52 +1300 Subject: [PATCH] update docs --- NAMESPACE | 1 + R/docs_types.R | 57 +++++++++++++++++++++++++++++++++++++++++++++ R/function.R | 15 ++++++++++++ R/types.R | 10 +++++++- _pkgdown.yml | 4 +++- man/ts_function.Rd | 13 +++++++++++ man/ts_object.Rd | 3 ++- man/ts_union.Rd | 14 +++++++++++ man/type_objects.Rd | 56 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 R/docs_types.R create mode 100644 man/ts_union.Rd create mode 100644 man/type_objects.Rd diff --git a/NAMESPACE b/NAMESPACE index 9cfd924..e50ce66 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,4 +29,5 @@ export(ts_list) export(ts_logical) export(ts_null) export(ts_numeric) +export(ts_union) export(ts_void) diff --git a/R/docs_types.R b/R/docs_types.R new file mode 100644 index 0000000..cb662ba --- /dev/null +++ b/R/docs_types.R @@ -0,0 +1,57 @@ +#' @title +#' Types in R and TypeScript +#' +#' @description +#' This document provides an overview of the main types available to +#' app developers, which includes the main types in R and their +#' TypeScript counterparts. +#' +#' @details +#' # TS objects +#' The basic object in `ts` is a `ts_object` class. This is represented by +#' input and return types, an optional default value, and a checking +#' function. +#' +#' Input types describe the `zod` schema of objects that TypeScript can pass +#' to Rserve functions. +#' +#' Return types describe the `zod` schema of objects that Rserve functions, +#' and most of these utilise the `Robj` utility types in the `rserve-ts` +#' library. The return types have additional properties added, +#' namedly `r_type` and `r_attributes`, handled by the `Robj` utility types. +#' +#' **Scalar versus array ("vector") types**: +#' In R, almost all types are vectors. In the 'rserve-js' library, +#' primitive arrays of length one are converted into scalars, which +#' leads to some issues with type checking when, for example, a return value +#' has unknown length. `which(x > 5)` is one such example. +#' +#' To solve this, we add an `n` argument to the `ts_*` functions. When `n = 1`, +#' the type takes the *scalar* form of the alue. When `n != 1`, the type takes +#' the *array* form of the value (this includes 0). Otherwise, the type +#' is the union of the scalar and array forms. +#' +#' This is the case for numbers, strings, and booleans. +#' +#' # Available types +#' +#' - `ts_boolean`: A boolean value. The array type is `Int8Array`. +#' - `ts_integer`: An integer value. The array type is `Int32Array`. +#' Javascript does not have a native integer type, +#' so scalars are represented as a number +#' (the same as `ts_numeric`). +#' - `ts_numeric`: A numeric value. The array type is `Float64Array`.* +#' - `ts_string`: A string value. The array type is `string[]`. +#' - `ts_factor`: A factor value. The array type is `(level1 | level2 | ... | levelN)[]`, and this type does not have a scalar form. +#' - `ts_list`: A list value, represented by a named object or an array. +#' - `ts_dataframe`: A data frame value, represented by a named object. +#' - `ts_null`: A null value. +#' - `ts_void`: A void value, used for specifying return types of functions +#' that do not return a value. +#' +#' +#' +#' @family type documentation +#' +#' @name type_objects +NULL diff --git a/R/function.R b/R/function.R index 41825bf..8e4d8e0 100644 --- a/R/function.R +++ b/R/function.R @@ -44,10 +44,25 @@ ts_result <- function(type, value) { #' TS function definition #' +#' @details +#' Defining functions is the core of writing Rserve apps. +#' Functions are referred to as *object capabilities* (ocaps), +#' as they are 'objects' that allow Javascript to access capabilities +#' of R with a restricted interface. Only arguments can be adjusted. +#' +#' TS functions can be defined using existing (named) or anonymous functions. +#' Anonymous functions are useful in that the arguments to the functions +#' can explicitly be defined with their types as formal arguments: +#' +#' ``` +#' ts_function(function(x = ts_integer(), y = ts_string()) { ... }) +#' ``` +#' #' @param f an R function #' @param ... argument definitions (only required if f does not specify these in its formals) #' @param result return type (ignored if overloads are provided) #' @export +#' @md ts_function <- function(f, ..., result = ts_void()) { args <- list(...) if (!is.null(result) && !is_ts_object(result)) { diff --git a/R/types.R b/R/types.R index e3f7a2c..073feba 100644 --- a/R/types.R +++ b/R/types.R @@ -1,6 +1,7 @@ #' Typed object #' -#' This is the base type for all typed objects. It is not meant to be used directly. +#' This is the base type for all typed objects, and can be used to define +#' custom types. #' #' @param input_type The type of the object that Typescript expect to send to R. #' @param return_type The type of the object that Typescript expects to recieve from R. @@ -111,7 +112,14 @@ 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 +#' @export +#' @md ts_union <- function(...) sprintf("z.union([%s])", paste(..., sep = ", ")) + ts_array <- function(type = c("z.number()", "z.boolean()", "z.string()")) { if (type == "z.number()") { return("z.instanceof(Float64Array)") diff --git a/_pkgdown.yml b/_pkgdown.yml index abccc4c..eb3e401 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1,7 +1,7 @@ url: http://tomelliott.co.nz/ts/ template: bootstrap: 5 - bootswatch: cosmo + bootswatch: simplex reference: - title: Building apps @@ -14,6 +14,7 @@ reference: - title: Types desc: Type helper functions for defining argument and return types. - contents: + - type_objects - ts_logical - ts_integer - ts_numeric @@ -24,3 +25,4 @@ reference: - ts_null - ts_void - ts_object + - ts_union diff --git a/man/ts_function.Rd b/man/ts_function.Rd index 2daaba5..cfc890f 100644 --- a/man/ts_function.Rd +++ b/man/ts_function.Rd @@ -16,3 +16,16 @@ ts_function(f, ..., result = ts_void()) \description{ TS function definition } +\details{ +Defining functions is the core of writing Rserve apps. +Functions are referred to as \emph{object capabilities} (ocaps), +as they are 'objects' that allow Javascript to access capabilities +of R with a restricted interface. Only arguments can be adjusted. + +TS functions can be defined using existing (named) or anonymous functions. +Anonymous functions are useful in that the arguments to the functions +can explicitly be defined with their types as formal arguments: + +\if{html}{\out{
}}\preformatted{ts_function(function(x = ts_integer(), y = ts_string()) \{ ... \}) +}\if{html}{\out{
}} +} diff --git a/man/ts_object.Rd b/man/ts_object.Rd index bbb2dca..10a44fb 100644 --- a/man/ts_object.Rd +++ b/man/ts_object.Rd @@ -39,7 +39,8 @@ check_type(type, x) \item{type}{A ts object} } \description{ -This is the base type for all typed objects. It is not meant to be used directly. +This is the base type for all typed objects, and can be used to define +custom types. } \section{Functions}{ \itemize{ diff --git a/man/ts_union.Rd b/man/ts_union.Rd new file mode 100644 index 0000000..0b679ab --- /dev/null +++ b/man/ts_union.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/types.R +\name{ts_union} +\alias{ts_union} +\title{Union type} +\usage{ +ts_union(...) +} +\arguments{ +\item{...}{Types to merge} +} +\description{ +Create a union of types. Currently this only accepts schemas as strings. +} diff --git a/man/type_objects.Rd b/man/type_objects.Rd new file mode 100644 index 0000000..1b344eb --- /dev/null +++ b/man/type_objects.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/docs_types.R +\name{type_objects} +\alias{type_objects} +\title{Types in R and TypeScript} +\description{ +This document provides an overview of the main types available to +app developers, which includes the main types in R and their +TypeScript counterparts. +} +\section{TS objects}{ +The basic object in \code{ts} is a \code{ts_object} class. This is represented by +input and return types, an optional default value, and a checking +function. + +Input types describe the \code{zod} schema of objects that TypeScript can pass +to Rserve functions. + +Return types describe the \code{zod} schema of objects that Rserve functions, +and most of these utilise the \code{Robj} utility types in the \code{rserve-ts} +library. The return types have additional properties added, +namedly \code{r_type} and \code{r_attributes}, handled by the \code{Robj} utility types. + +\strong{Scalar versus array ("vector") types}: +In R, almost all types are vectors. In the 'rserve-js' library, +primitive arrays of length one are converted into scalars, which +leads to some issues with type checking when, for example, a return value +has unknown length. \code{which(x > 5)} is one such example. + +To solve this, we add an \code{n} argument to the \verb{ts_*} functions. When \code{n = 1}, +the type takes the \emph{scalar} form of the alue. When \code{n != 1}, the type takes +the \emph{array} form of the value (this includes 0). Otherwise, the type +is the union of the scalar and array forms. + +This is the case for numbers, strings, and booleans. +} + +\section{Available types}{ +\itemize{ +\item \code{ts_boolean}: A boolean value. The array type is \code{Int8Array}. +\item \code{ts_integer}: An integer value. The array type is \code{Int32Array}. +Javascript does not have a native integer type, +so scalars are represented as a number +(the same as \code{ts_numeric}). +\item \code{ts_numeric}: A numeric value. The array type is \code{Float64Array}.* +\item \code{ts_string}: A string value. The array type is \code{string[]}. +\item \code{ts_factor}: A factor value. The array type is \code{(level1 | level2 | ... | levelN)[]}, and this type does not have a scalar form. +\item \code{ts_list}: A list value, represented by a named object or an array. +\item \code{ts_dataframe}: A data frame value, represented by a named object. +\item \code{ts_null}: A null value. +\item \code{ts_void}: A void value, used for specifying return types of functions +that do not return a value. +} +} + +\concept{type documentation}