Closed MilkWasABadChoice closed 7 years ago
Good question, thanks. There is a .checklist
argument in firmly
that accepts checks in a list, which you can use as a receptacle when delivering checks via %>%
. For example, if you want to add the check that a
and b
are numeric vectors of equal length and you want to keep these checks close to the function header, you can do the following:
library(magrittr)
library(valaddin)
vec_add <- list(
list(~a, ~b) ~ is.numeric,
list(~length(a) == length(b)) ~ isTRUE
) %>%
firmly(
function(a, b) {
a + b
},
.checklist = .
)
In this case, you can express the checks more succinctly (since is.numeric
is imposed "globally", on all arguments):
vec_add <- list(
~is.numeric, # Alternatively, globalize(vld_numeric)
vld_true(~length(a) == length(b))
) %>%
firmly(
function(a, b) {
a + b
},
.checklist = .
)
In fact, you're better off not using the pipe, at all (shorter and reads the same):
vec_add <- firmly(
~is.numeric,
vld_true(~length(a) == length(b)),
.f = function(a, b) {
a + b
}
)
@MilkWasABadChoice It is possible to do "reverse magrittr" for input validation, by defining a new operator (for which %<%
would not be the best name):
`%firmly%` <- function(.checklist, .f) firmly(.f, .checklist = .checklist)
vec_add <- list(
~is.numeric, vld_true(~length(a) == length(b))
) %firmly%
function(a, b) {
a + b
}
It'd be useful to have such an operator built into valaddin. Excellent idea, thanks!
Valaddin has exactly the semantics I've been looking for – the only drawback is that I can't find a way to leverage it without sacrificing readability and locality of semantics in code. When I'm defining a function in an explicitly typed language, it's easy for someone to see the intent by reading the function signature:
def doSomething(a: Numeric, b: Numeric): Numeric = ...
With valaddin, I'm stuck doing something like this:
I'm reluctant to adopt any convention that forces the reader to go all the way past the end of a function to find out the key information they need to understand its arguments. The only option I've come up with would be introducing a "reverse" magrittr-style %<% operator that pulls from right-to-left (haven't tried this, just hypothetically):
Apologies if this is stretching the nature of "Issue" into "Stylistic Grievance", but I really like Valaddin's design & want to adopt it. Is there anything you can suggest to make it possible to co-locate the function signature/declaration and the declaration of the semantic constraints, or at least allow them to be close enough that the reader's job of understanding the code isn't frustrated by not knowing what semantic expectations may or may not be intended by the code's author?