smbache / ensurer Goto Github PK
View Code? Open in Web Editor NEWEnsure values are as expected at runtime
License: Other
Ensure values are as expected at runtime
License: Other
Is this planned? E.g. ensure_string_scalar
, ensure_file_exists
, ensure_dir_exists
, etc? Or the idea is that I can just add to my package whatever I need?
Hello,
I wonder if try-errors could be forwarded in the same desirable way as normal errors are handled by the ensure() function:
require(ensurer)
require(magrittr)
stop("I want to see this error.") %>%
ensure(is.character, fail_with = stop("I don't want to see this error")
try({stop("I want to see this error.")}) %>%
ensure(is.character, fail_with = stop("I don't want to see this error"))
I promise that this is the last one for today. :)
As much as I like the dot notation, I think it would be good to see that name of the object that breached the contract (if it has a name at all). Often the name is informative. I would not replace the dot itself, but I think something like this looks good and is more informative:
ensure_small_even <- ensures_that( . < 50, . %% 2 == 0)
f <- function() {
value <- 101
ensure_small_even(value)
}
f()
Error: assertions failed for 'value' in 'f':
✖ all(. < 50)
✖ all(. %% 2 == 0)
It might be challenging to implement this, though. In the ensurer function, deparse(sys.call(-1)[[1]])
gives the function name, and deparse(sys.call()[[2]])
gives the argument name, this is easy.
But of course you can have anonymous functions, and you can also wrap ensurer functions, in which cases this is more difficult. You would probably need API to wrap an ensurer function. E.g. I am doing this now:
ensure_character_scalar <- function(x) {
x %>%
ensure_that(is.character(.)) %>%
ensure_that(length(.) == 1)
}
Which is not bad, but ensure_character_scalar
is not an ensurer function, just a plain one.
And other strange cases might exist, that I am unaware of.
since we now merge the two projects. I'll nuke type when this is done.
I guess this is possible with fail_with
, but it seems rather cumbersome. When I do something like
ensure_that(x, attr %in% names(attributes(.)))
the error message looks as
Error: The following condition failed:
* attr %in% names(attributes(.))
and I would rather like something like
Error: The following condition failed:
* has no attribute 'name'
Do you plan to do it some time?
Thanks for your work on this.
I quite like this package and considering using it as a dependency in a data cleaning package.
What are the chances that this package will make its way to a release version on CRAN?
I'm less interested in the type stability stuff than I am in having a lightweight way to create runtime contracts with custom error messages for use in production processes.
(Note that I have the same question about loggr -- love that package as well).
Dear @smbache,
Thanks a lot for this great package. I am frequently using it to ensure that data I read in from CSVs/data bases does not change unnoticed as well as that all my calculation stay in certain borders and no NAs suddenly occur after changes. As my alert system I use a fail_with function that forwards the error respective message to Slack (an instant messenger), which works great.
In practice every data source I read into R has its own functions (like get_customer_data(), get_sales_data(), ...). Each of these functions contains chained ensure_that statements that check for various cases. Following data operations are packed with ensurer checks as well.
# Error detection
dim_country %>%
ensurer::ensure_that(is.data.frame(.), fail_with = ensurer_fail_function) %>%
ensurer::ensure_that(ncol(.) == 2, fail_with = ensurer_fail_function) %>%
ensurer::ensure_that(nrow(.) > 1, fail_with = ensurer_fail_function) %>%
# Prevent duplicates
ensurer::ensure_that(length(.$country_code) == length(unique(.$country_code)), fail_with = ensurer_fail_function) %>%
ensurer::ensure_that(length(.$country) == length(unique(.$country)), fail_with = ensurer_fail_function) %>%
# No NAs in relevant columns
ensurer::ensure_that(any(is.na(.$country_code)) == FALSE, fail_with = ensurer_fail_function) %>%
ensurer::ensure_that(any(is.na(.$country)) == FALSE, fail_with = ensurer_fail_function) %>%
invisible(.)
As you can see, I have multiple cases I want to check. However, I have to provide each time that I want to call my individual fail_with function. This is tedious to code and one easily misses to enter an indivual fail_with function.
I see the possibility to use ensures_that here, which in the example above would reduce the time I type in fail_with = ensurer_fail_function to one for that example. However, in my case, I have around 20 different places with ensurer checks in one single complex script. That means even with ensures_that, I would still end up with having to define this 20 times with the same fail_with option for the whole script. Thus, my wish for a global option to define a fail_with function.
I am perfectly fine, if you disagree with me on this and say that you deem ensures_that as the solution to my wish. ;-) Again, thanks a lot for providing this useful package!
EDIT sorry, pressed enter by mistake.
I think being brief and succinct is a virtue. So how about
Errors: * all(. < 50)
* all(.%%2 == 0)
instead of
Error: The following condition(s) failed:
* all(. < 50)
* all(.%%2 == 0)
I have an ensurer function that I want to extend, ideally without writing out the full original contract again. I think currently the best I can do is putting the original and the new contracts together with a pipe (%,%
or %>%
). This is not bad, but unfortunately behaves slightly differently, as it does not list all errors, if there are some both in the original contract and in the additional one.
Would you consider some API to extend a contract?
See e.g. https://github.com/smbache/ensurer/blob/master/R/ensures_that.R#L106
Is this as intended? It falls apart in my editor as well....
Just an idea that came up as I was writing checks. It would be often useful to run the checks and get a TRUE/FALSE result instead of an error, similarly to see_if
in assertthat
.
Right now I need to duplicate the code for this, or use a single expression in ensure_that
:
is_adjmatrix <- function(x) (is.matrix(x) || is(x, "Matrix")) && nrow(x) == ncol(x)
ensure_adjmatrix <- ensures_that(is_adjmatrix(.))
But then of course individual failed conditions are not reported.
Just an idea to think about.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.