updating API
This commit is contained in:
parent
b2e62d757f
commit
7a4f649e70
@ -8,10 +8,10 @@ ts_compile.ts_function <- function(f, name = deparse(substitute(f)), ...) {
|
|||||||
inputs <- attr(f, "args")
|
inputs <- attr(f, "args")
|
||||||
result <- attr(f, "result")
|
result <- attr(f, "result")
|
||||||
|
|
||||||
inputs <- sapply(inputs, \(x) x$type)
|
inputs <- sapply(inputs, \(x) x$zod_type)
|
||||||
fn_args <- paste(inputs) |>
|
fn_args <- paste(inputs) |>
|
||||||
paste(collapse = ", ")
|
paste(collapse = ", ")
|
||||||
sprintf("const %s = R.ocap([%s], %s]);", name, fn_args, result$type_fn)
|
sprintf("const %s = R.ocap([%s], %s]);", name, fn_args, result$r_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
# #' @export
|
# #' @export
|
||||||
|
|||||||
28
R/types.R
28
R/types.R
@ -9,8 +9,8 @@
|
|||||||
#' @param generic logical, if `TRUE` then the object is a generic type.
|
#' @param generic logical, if `TRUE` then the object is a generic type.
|
||||||
#'
|
#'
|
||||||
#' @md
|
#' @md
|
||||||
object <- function(type = "any",
|
object <- function(zod_type = "any",
|
||||||
type_fn = "any",
|
r_type = "any",
|
||||||
default = NULL,
|
default = NULL,
|
||||||
check = function() stop("Not implemented"),
|
check = function() stop("Not implemented"),
|
||||||
generic = FALSE) {
|
generic = FALSE) {
|
||||||
@ -27,21 +27,21 @@ object <- function(type = "any",
|
|||||||
#' @export
|
#' @export
|
||||||
print.ts_object <- function(x, ...) {
|
print.ts_object <- function(x, ...) {
|
||||||
# name <- deparse(substitute(x))
|
# name <- deparse(substitute(x))
|
||||||
cat(sprintf("Input (ts) type: %s\n", x$type))
|
cat(sprintf("Zod type: %s\n", x$zod_type))
|
||||||
cat(sprintf("Output (R) type: %s\n", x$type_fn))
|
cat(sprintf(" R type: %s\n", x$r_type))
|
||||||
}
|
}
|
||||||
|
|
||||||
is_object <- function(x) {
|
is_object <- function(x) {
|
||||||
inherits(x, "ts_object")
|
inherits(x, "ts_object")
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_union <- function(...) paste(..., sep = " | ")
|
ts_union <- function(...) sprintf("z.union([%s])", paste(..., sep = ", "))
|
||||||
ts_array <- function(type = c("number", "boolean", "string")) {
|
ts_array <- function(type = c("z.number()", "z.boolean()", "z.string()")) {
|
||||||
if (type == "number") {
|
if (type == "z.number()") {
|
||||||
return("Float64Array")
|
return("z.instanceof(Float64Array)")
|
||||||
}
|
}
|
||||||
if (type == "boolean") {
|
if (type == "z.boolean()") {
|
||||||
return("Uint8Array")
|
return("z.instanceof(Uint8Array)")
|
||||||
}
|
}
|
||||||
return("RTYPE.stringArray")
|
return("RTYPE.stringArray")
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ n_type_fun <- function(n, type) {
|
|||||||
#' @export
|
#' @export
|
||||||
ts_logical <- function(n = -1L) {
|
ts_logical <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "boolean"),
|
n_type(n, "z.boolean()"),
|
||||||
n_type_fun(n, "RTYPE.logical"),
|
n_type_fun(n, "RTYPE.logical"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.logical(x)) stop("Expected a boolean")
|
if (!is.logical(x)) stop("Expected a boolean")
|
||||||
@ -78,7 +78,7 @@ ts_logical <- function(n = -1L) {
|
|||||||
#' @export
|
#' @export
|
||||||
ts_integer <- function(n = -1L) {
|
ts_integer <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "number"),
|
n_type(n, "z.number()"),
|
||||||
n_type_fun(n, "RTYPE.integer"),
|
n_type_fun(n, "RTYPE.integer"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.integer(x)) stop("Expected an integer")
|
if (!is.integer(x)) stop("Expected an integer")
|
||||||
@ -91,7 +91,7 @@ ts_integer <- function(n = -1L) {
|
|||||||
#' @export
|
#' @export
|
||||||
ts_numeric <- function(n = -1L) {
|
ts_numeric <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "number"),
|
n_type(n, "z.number()"),
|
||||||
n_type_fun(n, "RTYPE.numeric"),
|
n_type_fun(n, "RTYPE.numeric"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.numeric(x)) stop("Expected a number", call. = FALSE)
|
if (!is.numeric(x)) stop("Expected a number", call. = FALSE)
|
||||||
@ -106,7 +106,7 @@ ts_numeric <- function(n = -1L) {
|
|||||||
#' @export
|
#' @export
|
||||||
ts_character <- function(n = -1L) {
|
ts_character <- function(n = -1L) {
|
||||||
object(
|
object(
|
||||||
n_type(n, "string"),
|
n_type(n, "z.string()"),
|
||||||
n_type_fun(n, "RTYPE.character"),
|
n_type_fun(n, "RTYPE.character"),
|
||||||
check = function(x) {
|
check = function(x) {
|
||||||
if (!is.character(x)) stop("Expected a string")
|
if (!is.character(x)) stop("Expected a string")
|
||||||
|
|||||||
26
README.Rmd
26
README.Rmd
@ -36,27 +36,24 @@ Writing functions is easy, just use the `ts_*()` functions to define formals and
|
|||||||
|
|
||||||
```r
|
```r
|
||||||
library(ts)
|
library(ts)
|
||||||
app <- ts_app(
|
app <- ts_list(
|
||||||
add = ts_fun(
|
add = ts_fun(
|
||||||
function(x, y) {
|
function(x, y) {
|
||||||
x + y
|
x + y
|
||||||
},
|
},
|
||||||
x = ts_number(),
|
x = ts_number(1),
|
||||||
y = ts_number(),
|
y = ts_number(1),
|
||||||
# ideally this will use a generic type where x OR y can be vectors
|
# ideally this will use a generic type where x OR y can be vectors
|
||||||
# and, if one is a vector, the return type will be a vector too...
|
# and, if one is a vector, the return type will be a vector too...
|
||||||
result = ts_number()
|
result = r_numeric(1)
|
||||||
),
|
),
|
||||||
sample = ts_fun(
|
sample = ts_fun(
|
||||||
function(x, n) {
|
function(x, n) {
|
||||||
sample(x, n)
|
sample(x, n)
|
||||||
},
|
},
|
||||||
x = ts_character_vector(),
|
x = ts_string(),
|
||||||
n = ts_integer(),
|
n = ts_number(1),
|
||||||
result = ts_condition(n,
|
result = r_character()
|
||||||
1 = ts_character(),
|
|
||||||
ts_character_vector()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,7 +70,7 @@ export const app = {
|
|||||||
z.promise(R.numeric(1))
|
z.promise(R.numeric(1))
|
||||||
),
|
),
|
||||||
sample: z.function(
|
sample: z.function(
|
||||||
z.tuple([z.character_vector(), z.integer()]),
|
z.tuple([z.array(z.string()), z.integer()]),
|
||||||
z.promise(R.character())
|
z.promise(R.character())
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -82,11 +79,8 @@ export const app = {
|
|||||||
which will generate the following types:
|
which will generate the following types:
|
||||||
```typescript
|
```typescript
|
||||||
type App = {
|
type App = {
|
||||||
add: (x: number, y: number) => Promise<{ data: number }>;
|
add: (x: number, y: number) => Promise<Robj.Numeric<1>>;
|
||||||
sample: (x: string[], n: number) => Promise<{ data: string | string[] }>;
|
sample: (x: string[], n: number) => Promise<Robj.Character>;
|
||||||
// or, if possible, even better:
|
|
||||||
sample: <N extends number>(x: string[], n: N) =>
|
|
||||||
Promise<{ data: N extends 1 ? string : string[] }>;
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
32
README.md
32
README.md
@ -28,27 +28,24 @@ formals and return types.
|
|||||||
|
|
||||||
``` r
|
``` r
|
||||||
library(ts)
|
library(ts)
|
||||||
app <- ts_app(
|
app <- ts_list(
|
||||||
add = ts_fun(
|
add = ts_fun(
|
||||||
function(x, y) {
|
function(x, y) {
|
||||||
x + y
|
x + y
|
||||||
},
|
},
|
||||||
x = ts_number(),
|
x = ts_number(1),
|
||||||
y = ts_number(),
|
y = ts_number(1),
|
||||||
# ideally this will use a generic type where x OR y can be vectors
|
# ideally this will use a generic type where x OR y can be vectors
|
||||||
# and, if one is a vector, the return type will be a vector too...
|
# and, if one is a vector, the return type will be a vector too...
|
||||||
result = ts_number()
|
result = r_numeric(1)
|
||||||
),
|
),
|
||||||
sample = ts_fun(
|
sample = ts_fun(
|
||||||
function(x, n) {
|
function(x, n) {
|
||||||
sample(x, n)
|
sample(x, n)
|
||||||
},
|
},
|
||||||
x = ts_character_vector(),
|
x = ts_string(),
|
||||||
n = ts_integer(),
|
n = ts_number(1),
|
||||||
result = ts_condition(n,
|
result = r_character()
|
||||||
1 = ts_character(),
|
|
||||||
ts_character_vector()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -66,7 +63,7 @@ export const app = {
|
|||||||
z.promise(R.numeric(1))
|
z.promise(R.numeric(1))
|
||||||
),
|
),
|
||||||
sample: z.function(
|
sample: z.function(
|
||||||
z.tuple([z.character_vector(), z.integer()]),
|
z.tuple([z.array(z.string()), z.integer()]),
|
||||||
z.promise(R.character())
|
z.promise(R.character())
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -76,11 +73,8 @@ which will generate the following types:
|
|||||||
|
|
||||||
``` typescript
|
``` typescript
|
||||||
type App = {
|
type App = {
|
||||||
add: (x: number, y: number) => Promise<{ data: number }>;
|
add: (x: number, y: number) => Promise<Robj.Numeric<1>>;
|
||||||
sample: (x: string[], n: number) => Promise<{ data: string | string[] }>;
|
sample: (x: string[], n: number) => Promise<Robj.Character>;
|
||||||
// or, if possible, even better:
|
|
||||||
sample: <N extends number>(x: string[], n: N) =>
|
|
||||||
Promise<{ data: N extends 1 ? string : string[] }>;
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -113,7 +107,11 @@ cat(readLines("tests/testthat/app.R"), sep = "\n")
|
|||||||
#> )
|
#> )
|
||||||
|
|
||||||
ts_compile("tests/testthat/app.R", file = "")
|
ts_compile("tests/testthat/app.R", file = "")
|
||||||
#> Error in ts_compile.ts_function(e[[x]], file = file, name = x): unused argument (file = file)
|
#> import { stringArray, character, numeric } from 'rserve-ts';
|
||||||
|
#>
|
||||||
|
#> const fn_first = R.ocap([z.union([z.string(), stringArray])], character(1)]);
|
||||||
|
#> const fn_mean = R.ocap([z.union([z.number(), z.instanceof(Float64Array)])], numeric(1)]);
|
||||||
|
#> const sample_num = R.ocap([z.instanceof(Float64Array)], numeric(1)]);
|
||||||
```
|
```
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|||||||
@ -5,23 +5,23 @@
|
|||||||
\title{Typed object}
|
\title{Typed object}
|
||||||
\usage{
|
\usage{
|
||||||
object(
|
object(
|
||||||
type = "any",
|
zod_type = "any",
|
||||||
type_fn = "any",
|
r_type = "any",
|
||||||
default = NULL,
|
default = NULL,
|
||||||
check = function() stop("Not implemented"),
|
check = function() stop("Not implemented"),
|
||||||
generic = FALSE
|
generic = FALSE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
\arguments{
|
\arguments{
|
||||||
\item{type}{The type of the object that Typescript expect to send to R.}
|
|
||||||
|
|
||||||
\item{type_fn}{The type of the object that Typescript expects to recieve from R.}
|
|
||||||
|
|
||||||
\item{default}{The default value of the object.}
|
\item{default}{The default value of the object.}
|
||||||
|
|
||||||
\item{check}{A function that checks the object and returns it if it is valid. This operates on the R side and is mostly for development and debugging purposes. It is up to the developer to ensure that all functions return the correct type of object always.}
|
\item{check}{A function that checks the object and returns it if it is valid. This operates on the R side and is mostly for development and debugging purposes. It is up to the developer to ensure that all functions return the correct type of object always.}
|
||||||
|
|
||||||
\item{generic}{logical, if \code{TRUE} then the object is a generic type.}
|
\item{generic}{logical, if \code{TRUE} then the object is a generic type.}
|
||||||
|
|
||||||
|
\item{type}{The type of the object that Typescript expect to send to R.}
|
||||||
|
|
||||||
|
\item{type_fn}{The type of the object that Typescript expects to recieve from R.}
|
||||||
}
|
}
|
||||||
\description{
|
\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. It is not meant to be used directly.
|
||||||
|
|||||||
@ -4,9 +4,24 @@ sample_num <- ts_function(
|
|||||||
x = ts_numeric(0),
|
x = ts_numeric(0),
|
||||||
result = ts_numeric(1)
|
result = ts_numeric(1)
|
||||||
)
|
)
|
||||||
ts_compile(sample_num)
|
|
||||||
|
sampler <- ts_function(
|
||||||
|
function() {
|
||||||
|
list(
|
||||||
|
sample_one = sample_num(0)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
result = ts_list(
|
||||||
|
num = sample_num
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ts_compile(d_normal)
|
||||||
|
|
||||||
# compile to:
|
# compile to:
|
||||||
# const out = {
|
# const sampler = R.ocap(
|
||||||
# sample_one: R.ocap([R.as_vector(z.number())], R.numeric(1)),
|
# [],
|
||||||
# };
|
# R.list({
|
||||||
|
# num: R.ocap([], R.numeric(1))
|
||||||
|
# })
|
||||||
|
# );
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user