Changes in version 0.5.0.9001 - to() now dispatches to to_date(), to_dttm(), to_time(), and to_dur() for Date, POSIXct, hms, and Period prototypes, respectively, and falls back to vctrs::vec_cast() for other prototype classes (#366, #367). Bug fixes - stbl_to() (C API) failures now have the same classes, messages, and fields as to() errors. stbl_to() gains x_arg and call arguments for error context; pass R_NilValue to use the defaults (#369). - to_date(), to_dbl(), to_dttm(), to_dur(), to_int(), to_lst(), and to_time() now raise errors instead of vctrs or base errors when the default method cannot coerce x (such as raw vectors) (#369). - to_chr() now has a dedicated condition method that returns a single string including the full condition class hierarchy and message in snapshot-style formatting (#258). It also now converts formulas to a single readable string (for example, "x ~ y") (#259). Changes in version 0.5.0 (2026-09-13) Breaking changes - stabilize_present() is now named assert_present(), since it doesn't stabilize (coerce) its input; it only asserts that the input is not NULL. Calling stabilize_present() now throws a "deprecated"-classed error directing you to assert_present() (#299). - expect_pkg_error_snapshot(), expect_pkg_message_snapshot(), and expect_pkg_warning_snapshot() now produce snapshots that mirror testthat::expect_snapshot(), showing the bare expression under Code and the condition class alongside its message (#301). Error messages for element-wise and incompatible-value failures also now list the failing locations and, where relevant, values, and the condition objects carry matching locations and values elements (#274, #332). Existing snapshots of these messages must be re-accepted; use testthat::skip_if_not_installed("stbl", minimum_version = "0.5.0") to skip such tests with older versions of {stbl}. New features - New assertion functions assert_not() and assert_contains(): assert_not() errors when x would be accepted (coerced or validated) by a single spec, and assert_contains() checks that the number of elements matching a spec falls within a given range (#289, #290). - New functions ignore_stbl_error() and replace_stbl_error() catch a {stbl} error of a given subclass (defaulting to any {stbl} error). ignore_stbl_error() returns NULL, allowing callers to suppress expected validation failures; replace_stbl_error() replaces the error's message with a custom one, with an optional additional_class argument to prepend extra classes to the error class list (#178, #334). - New "meta-stabilizer" functions compose other stabilizers and specs: stabilize_all_of() requires every stabilizer in ... to succeed, stabilize_any_of() returns the first successful result, stabilize_one_of() requires exactly one success, and stabilize_each() applies a single spec to every element. Matching to_*() and specify_*() variants are also available (#215, #278, #285, #286, #287, #288). - The stabilize_*() and specify_*() functions gain new constraint arguments: min_characters/max_characters for character vectors (#275), allowed_values to restrict input to a fixed set of permitted values (#282), exclusive_min_value/exclusive_max_value for strict numeric bounds (#276), multiple_of to require values that are a multiple of a given value (#283), and unique/.unique to reject duplicate elements (#280). See each function's documentation for details. - New date, dttm, time, and dur function families (to_date(), stabilize_date(), to_dttm(), stabilize_dttm(), to_time(), stabilize_time(), to_dur(), stabilize_dur(), plus matching specify_*() factories) validate and coerce RFC 3339 / ISO 8601 temporal values. stabilize_date() and stabilize_dttm() also accept unambiguous locale-dependent formats via a new accepted_datetime_formats argument and the locale_datetime_formats() helper (#104, #105, #294, #295, #326). - stabilize_df() and stabilize_lst() (and their specify_*() factories) are more flexible about named elements: .required marks named specs as optional (#279), .extra_cols/.named/.unnamed accept TRUE to allow extra or unnamed elements unchecked (#281), and .allow_zero_length lets a zero-length input skip the required-element check (#344). Bug fixes - stabilize_lst() (and stabilize_df(), which delegates to it) now correctly detects missing required named elements even when .x has no named elements at all, such as list() or list(1L, 2L). Previously, the required-element check was silently skipped whenever .x had no named elements (#344). - to_chr(), to_dbl(), to_fct(), to_int(), and to_lgl() now throw an informative "incompatible values" error listing the failing locations and values when a list contains elements that can't be converted, instead of a generic "can't coerce" error (#273, #335). - to_fct() and related factor helpers now support an ordered argument, preserving ordered factors by default and allowing to(..., factor(...)) to inherit orderedness from either x or .to (#246). - stabilize_*(NULL, allow_null = TRUE) always returns NULL, without checking other stabilize_*() rules. For example, stabilize_int(NULL, min_value = 1) now returns NULL, rather than erroring (#353). Changes in version 0.4.0 (2026-07-28) Breaking changes - to_df() and to_lst() now error if extra arguments are passed in .... Previously, these extra arguments were silently discarded (#200). - to_chr() now converts named functions to a string representing their name instead of erroring. Package functions are returned as "pkg::fn" (e.g., to_chr(mean) returns "base::mean"). Anonymous functions still produce an informative error. This behavior extends to to_chr_scalar(), stabilize_chr(), and stabilize_chr_scalar() (#251). New functions - New pkg_inform() and pkg_warn() signal classed messages and warnings, respectively, with an opinionated class hierarchy, mirroring pkg_abort(). New expect_pkg_message_classes() and expect_pkg_warning_classes() test that the expected classes are thrown, and expect_pkg_message_snapshot() and expect_pkg_warning_snapshot() snapshot-test the full output in one step (#213). - New function to() coerces x to the type of its .to argument. stbl_to() is also registered as a C callable in a new public C API (#182). - New to_fn(), are_fn_ish(), and is_fn_ish() add the fn type family to stbl. to_fn() coerces strings and symbols to functions. is_fn_ish() checks whether a single object can be safely coerced to a function. are_fn_ish() checks each element of a character vector for syntactic fn-ishness (bare name or "pkg::fn" form) (#250). Bug fixes - expect_pkg_error_snapshot(), expect_pkg_message_snapshot(), and expect_pkg_warning_snapshot() now produce stable snapshots when run under devtools::test_coverage_active_file(). specify_*() functions now also produce stable function-body snapshots under coverage (#253). - expect_pkg_message_classes() and expect_pkg_warning_classes() now support assignments inside object (e.g. result <- fn_that_warns()). expect_pkg_message_snapshot() and expect_pkg_warning_snapshot() inherit the same fix (#234). Other changes - are_*_ish(), to_*(), stabilize_dbl(), and stabilize_int() are all significantly faster for large vectors, with benchmarks showing roughly 3–20× throughput improvements (#217, #218, #219, #220, #221, #226, #239). - The are_*_ish(), to_*(), and range-check functions are now registered as C callables, as are the *_to_chr and *_to_fct families (stbl_chr_to_fct(), stbl_dbl_to_chr(), stbl_dbl_are_chrish(), stbl_fct_to_chr(), stbl_fct_are_chrish(), stbl_int_to_chr(), stbl_int_are_chrish(), stbl_int_to_fct(), stbl_lgl_to_chr(), and stbl_lgl_are_chrish()) (#235, #237, #241). - is_fct_ish() now accepts a max_levels argument to limit the number of unique non-NA levels (#231). Changes in version 0.3.0 (2026-04-04) Breaking changes - to_chr_scalar(), to_dbl_scalar(), to_fct_scalar(), to_int_scalar(), to_lgl_scalar(), stabilize_chr_scalar(), stabilize_dbl_scalar(), stabilize_fct_scalar(), stabilize_int_scalar(), stabilize_lgl_scalar(), specify_chr_scalar(), specify_dbl_scalar(), specify_fct_scalar(), specify_int_scalar(), and specify_lgl_scalar() (and their synonyms) now default to allow_null = FALSE and allow_zero_length = FALSE. Pass allow_null = TRUE or allow_zero_length = TRUE to restore the previous behavior (#189, #197). Potential breaking changes - Several conditions that formerly included a subclass of "stbl-error-must" no longer include that subclass. This only occurs when "stbl-error-must" was not the most specific subclass (i.e., when a more specific subclass was already included), and therefore should not impact most if any code (#136). New features - New long-form and British-spelling synonym functions for all class functions. For example, to_character() is a synonym for to_chr(), specify_logical() for specify_lgl(), and stabilise_*() for all stabilize_*() functions (#164, #167). - New expect_pkg_error_classes() checks that an error with the expected set of classes is thrown by pkg_abort(), and expect_pkg_error_snapshot() snapshot-tests the full error output in one step by combining expect_snapshot() with expect_pkg_error_classes() (#136, #188). New pkg_abort() throws errors with a standardized, opinionated collection of classes (#136). - New specification functions: specify_*() creates a "stbl_specified_fn", a call to the corresponding stabilize_*() function with arguments pre-filled. For example, stabilize_email <- specify_chr(regex = "^[^@]+@[^@]+\\.[^@]+$") creates a stabilize_email() function that validates email addresses (#147, #148, #149, #150, #151, #153, #161). - New stabilize_df() and specify_df() validate data frame structure and contents (#142). - New stabilize_lst() and specify_lst() validate list structure and contents and create pre-configured validators for nested validation (#110, #204). - New stabilize_present() validates that a value is non-NULL without imposing any type constraints (#110). - New to_df() (and synonym to_data_frame()) coerces compatible objects to a data frame, including named lists and named atomic vectors (e.g., to_df(letters)), with informative errors for incompatible inputs such as jagged lists (#142, #201, #203). - New to_lst() (and synonym to_list()) coerces an object to a list, with conditional checks for NULL and functions (#157, #166). Other changes - Revised the "Getting started with stbl" vignette to clarify what happens at each step (#139, #143, #144). - Clarified error messages (#176, #177). Changes in version 0.2.0 (2025-09-16) New features - New predicate functions check if an object can be safely coerced to a specific type. The is_*_ish() family (is_chr_ish(), is_dbl_ish(), is_fct_ish(), is_int_ish(), and is_lgl_ish()) checks the entire object at once. The are_*_ish() family (are_chr_ish(), are_dbl_ish(), are_fct_ish(), are_int_ish(), and are_lgl_ish()) checks each element of a vector individually (#23, #93). - New functions for working with doubles are available: to_dbl(), to_dbl_scalar(), stabilize_dbl(), and stabilize_dbl_scalar() (#23). - stabilize_chr() now accepts patterns from stringr::regex(), stringr::fixed(), and stringr::coll() (#87), and can generate more informative error messages for regex failures via the new regex_must_match() and regex_must_not_match() helper functions (#52, #85, #86, #89). Minor improvements and fixes - Error messages are now clearer and more standardized throughout the package (#95). - to_*() functions now consistently flatten list-like inputs when no information would be lost in the process (#128). - to_fct() now lists the allowed values in its error message when a value is not in the expected set, making it easier to debug (#67). - to_lgl() now coerces character representations of numbers (e.g., "0" and "1") to FALSE and TRUE respectively (#30). Documentation - The purpose of and vision for this package are now more clearly described in documentation (#56, #77). - New vignette("stbl") provides an overview of the package and its functions (#42). Changes in version 0.1.1 (2024-05-23) - Update formatting in DESCRIPTION and examples. Changes in version 0.1.0 - Initial CRAN submission.