Skip to content

Commit 6865c45

Browse files
committed
Refactor types
1 parent 79bb9ed commit 6865c45

File tree

9 files changed

+181
-167
lines changed

9 files changed

+181
-167
lines changed

NAMESPACE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ S3method(print,typewriter)
66
export(base_model)
77
export(check_args)
88
export(dtype)
9-
export(either)
109
export(is_any)
1110
export(is_typewriter_model)
1211
export(model_dump)

R/errors.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ create_type_check_error_message <- function(error) {
2323

2424
msg <- c(
2525
glue::glue("---\nType check failed for '{error$name}'"),
26-
paste0("value:", value_text),
26+
paste("value:", value_text),
2727
paste("type:", typeof(value)),
2828
paste("class:", class_text),
2929
paste("length:", length(value)),

R/types.R

Lines changed: 26 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ is_any <- function(x) TRUE
1919

2020
# ---
2121
# DEPRECATED
22-
Any <- function(n = NULL) {
23-
if (is.null(x)) {
24-
return(is_any)
25-
}
26-
return(function(x) length(x) == n)
27-
}
22+
#Any <- function(n = NULL) {
23+
# if (is.null(x)) {
24+
# return(is_any)
25+
# }
26+
# return(function(x) length(x) == n)
27+
#}
2828

2929
#' Type predicate `typewriter model`
3030
#' @param model_fn A model factory function created with [base_model()].
@@ -46,7 +46,11 @@ create_model_field <- function(
4646
n = NULL,
4747
optional = FALSE) {
4848
# Body
49-
type_str <- match.arg(dtype)
49+
dtype <- match.arg(dtype)
50+
if (dtype == "any") {
51+
return(model_field(fn = is_any))
52+
}
53+
5054
base_fn <- function(x) typeof(x) == dtype
5155
if (dtype == "logical") {
5256
base_fn <- is_logical
@@ -124,123 +128,27 @@ as_model_field <- function(x) {
124128
model_field_from_vec(x)
125129
}
126130

127-
# ---
128-
#' Create a model field
129-
#' @param x A type check function or type string.
130-
#' @param default A default value.
131-
#' @param optional description
132-
#' @returns A type check function
133-
#' @export
134-
dtype <- function(x, default = NA, optional = FALSE) {
135-
field <- as_model_field(x)
136-
field$default <- default
137-
field$optional <- optional
138-
return(field)
139-
}
140-
141-
# ---
142-
# Helper
143-
# DEPRECATED
144-
as_type_check_func <- function(type_check) {
145-
if (is.character(type_check)) {
146-
type_check <- type_check_fn_from_str(type_check)
147-
}
148-
149-
rlang::as_function(type_check)
150-
}
151-
#### DEPRECATED ####
152-
153-
# ---
154131
#' Mark a parameter as optional
155-
#' @param type_check_fn Type check function or type string.
156-
#' @example examples/api/type-is-optional.R
157-
#' @returns type check function
132+
#' @param obj A type definition object.
133+
#' @returns A [model_field()] with `optional = TRUE`.
158134
#' @export
159-
# TODO: Refactor to support model_fields
160-
optional <- function(type_check_fn) {
161-
if (inherits(type_check_fn, CLASS_MODEL_FIELD)) {
162-
stop(CLASS_MODEL_FIELD, " objects are not supported.")
135+
optional <- function(obj) {
136+
if (!inherits(obj, CLASS_MODEL_FIELD)) {
137+
obj <- as_model_field(obj)
163138
}
164139

165-
type_check_fn <- as_type_check_func(type_check_fn)
166-
new_type_check_fn <- structure(
167-
function(x) type_check_fn(x) | rlang::is_na(x),
168-
base_func = type_check_fn
169-
)
170-
new_type_check_fn
140+
obj$optional <- TRUE
141+
return(obj)
171142
}
172143

173144
# ---
174-
#' Allow multiple types
175-
#' @param ... Type check functions or type strings
176-
#' @returns A type check function
177-
#' @example examples/api/types-union.R
145+
#' Create a model field/type definition
146+
#' @param x A type check function or type string.
147+
#' @param default A default value.
148+
#' @returns A [model_field()].
178149
#' @export
179-
either <- function(...) {
180-
fns <- lapply(list(...), as_type_check_func)
181-
structure(
182-
function(x) {
183-
any(unlist(lapply(fns, function(fn) fn(x))))
184-
},
185-
base_func = fns
186-
)
187-
}
188-
189-
# ---
190-
# Helper
191-
base_type <- function(
192-
type_str = c("integer", "double", "character", "logical", "list", "raw", "complex", "any"),
193-
n = NULL,
194-
default = NA) {
195-
match.arg(type_str)
196-
if (type_str == "any") {
197-
return(is_any)
198-
}
199-
200-
body <- substitute(typeof(x) == dtype, list(dtype = type_str))
201-
202-
if (is_not_null(n)) {
203-
body <- substitute(
204-
typeof(x) == dtype & length(x) == n,
205-
list(dtype = type_str, n = as.integer(n))
206-
)
207-
}
208-
209-
fn <- rlang::new_function(alist(x = ), body)
210-
if (!is.na(default)) {
211-
return(model_field(fn, default))
212-
}
213-
214-
return(fn)
215-
}
216-
217-
# --- Experimental
218-
219-
# ---
220-
type_integer <- function(n = NULL, default = NA) {
221-
base_type("integer", n, default)
222-
}
223-
224-
# ---
225-
type_double <- function(n = NULL, default = NA) {
226-
base_type("double", n, default)
227-
}
228-
229-
# ---
230-
type_character <- function(n = NULL, default = NA) {
231-
base_type("character", n, default)
232-
}
233-
234-
# ---
235-
type_logical <- function(n = NULL, default = NA) {
236-
base_type("logical", n, default)
237-
}
238-
239-
# ---
240-
# DEPRECATED
241-
dtype_integer <- function(n = NULL) {
242-
fn <- function(x) {
243-
typeof(x) == "integer" & length(x) == n
244-
}
245-
structure(fn, dtype = "integer", n = n)
150+
dtype <- function(x, default = NA) {
151+
field <- as_model_field(x)
152+
field$default <- default
153+
return(field)
246154
}

_obsolete/types-obs.R

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# ---
2+
# Helper
3+
# DEPRECATED
4+
as_type_check_func <- function(type_check) {
5+
if (is.character(type_check)) {
6+
type_check <- type_check_fn_from_str(type_check)
7+
}
8+
9+
rlang::as_function(type_check)
10+
}
11+
#### DEPRECATED ####
12+
13+
# ---
14+
#' Mark a parameter as optional
15+
#' @param type_check_fn Type check function or type string.
16+
#' @example examples/api/type-is-optional.R
17+
#' @returns type check function
18+
#' @export
19+
# TODO: Refactor to support model_fields
20+
optional_obs <- function(type_check_fn) {
21+
if (inherits(type_check_fn, CLASS_MODEL_FIELD)) {
22+
stop(CLASS_MODEL_FIELD, " objects are not supported.")
23+
}
24+
25+
type_check_fn <- as_type_check_func(type_check_fn)
26+
new_type_check_fn <- structure(
27+
function(x) type_check_fn(x) | rlang::is_na(x),
28+
base_func = type_check_fn
29+
)
30+
new_type_check_fn
31+
}
32+
33+
# ---
34+
#' Allow multiple types
35+
#' @param ... Type check functions or type strings
36+
#' @returns A type check function
37+
#' @example examples/api/types-union.R
38+
#' @export
39+
either <- function(...) {
40+
fns <- lapply(list(...), as_type_check_func)
41+
structure(
42+
function(x) {
43+
any(unlist(lapply(fns, function(fn) fn(x))))
44+
},
45+
base_func = fns
46+
)
47+
}
48+
49+
# ---
50+
# Helper
51+
base_type <- function(
52+
type_str = c("integer", "double", "character", "logical", "list", "raw", "complex", "any"),
53+
n = NULL,
54+
default = NA) {
55+
match.arg(type_str)
56+
if (type_str == "any") {
57+
return(is_any)
58+
}
59+
60+
body <- substitute(typeof(x) == dtype, list(dtype = type_str))
61+
62+
if (is_not_null(n)) {
63+
body <- substitute(
64+
typeof(x) == dtype & length(x) == n,
65+
list(dtype = type_str, n = as.integer(n))
66+
)
67+
}
68+
69+
fn <- rlang::new_function(alist(x = ), body)
70+
if (!is.na(default)) {
71+
return(model_field(fn, default))
72+
}
73+
74+
return(fn)
75+
}
76+
77+
# --- Experimental
78+
79+
# ---
80+
type_integer <- function(n = NULL, default = NA) {
81+
base_type("integer", n, default)
82+
}
83+
84+
# ---
85+
type_double <- function(n = NULL, default = NA) {
86+
base_type("double", n, default)
87+
}
88+
89+
# ---
90+
type_character <- function(n = NULL, default = NA) {
91+
base_type("character", n, default)
92+
}
93+
94+
# ---
95+
type_logical <- function(n = NULL, default = NA) {
96+
base_type("logical", n, default)
97+
}
98+
99+
# ---
100+
# DEPRECATED
101+
dtype_integer <- function(n = NULL) {
102+
fn <- function(x) {
103+
typeof(x) == "integer" & length(x) == n
104+
}
105+
structure(fn, dtype = "integer", n = n)
106+
}

examples/playground-and-experimental.R

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ mtcars_model <- base_model(
7171
cyl = as.integer,
7272
gear = as.integer
7373
),
74-
.model_config = model_config(extra = "forbid")
74+
.extra = "forbid"
7575
)
7676

7777
mtcars_model(mtcars)
@@ -170,3 +170,32 @@ mt <- typed_struct(
170170
)
171171

172172
mt(a = iris$Sepal.Length, b = TRUE)
173+
174+
# ---
175+
a_cool_type <- typed_struct(
176+
a = "integer",
177+
b = optional("logical"),
178+
x = optional(dtype("character", "1")),
179+
y = optional(character(1))
180+
)
181+
182+
a_cool_type(a = 1L, b = T, y= LETTERS[1:2])
183+
184+
f_test <- function(a = dtype("integer", 10L)) {
185+
check_args()
186+
a
187+
}
188+
189+
f_test(a = 1L)
190+
f_test()
191+
192+
#
193+
my_struct <- typed_struct(
194+
a = \(a) is.integer(a) & a > 2
195+
)
196+
197+
my_struct(a = 3L)
198+
199+
df <- data.frame(a = 4:9)
200+
201+
my_struct(df)

man/dtype.Rd

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/either.Rd

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)