Skip to content

feat: assert_contains() function #290

Description

@jonthegeek

Summary

As a package developer, in order to require that a vector or list contains a certain number of elements matching a specification, I would like constraints that count how many elements satisfy a spec and enforce minimum and/or maximum counts.

Signature

assert_contains(
  x,
  spec,
  ...,
  min_matches = 1,
  max_matches = NULL),
  x_arg = caller_arg(x),
  call = caller_env(),
  x_class = object_type(x)
  • x: The object to check (as documented in R/aaa-shared_params.R and inherited here).
  • spec: Same as in feat: stabilize_each() #287 and feat: assert_not() #289. Create a single definition in R/aaa-shared_params.R that works for all three issues.
  • min_matches: Minimum number of elements that must match spec. Must be >= 1.
  • max_matches: Maximum number of elements that can match spec. Must be >= min_matches.
  • ...: Check with rlang::check_dots_empty() and document with @inheritParams rlang::args_dots_empty.
  • x_arg, call, x_class: As inherited from .shared-params

Details

JSON Schema arrays can require that at least (minContains) and at most (maxContains) some number of elements validate against a subschema named by contains. This is a cardinality constraint over a spec, distinct from stabilize_each() (#287), which requires that every element match a single spec.

Add a new function assert_contains(). I envision using this as part of a suite of checks. The function should return x unchanged if it passes the check. It should determine how many elements of x match the given spec, and compare that number to min_matches and max_matches. Run the object through the stabilizer, and catch the result. If it passes, all elements should be counted. If it fails, and the failure includes a locations object (as implemented in #274 and expanded since then), all elements not in locations count as matches.

JSON Schema connection

  • contains: <S> → at least one element matches <spec for S> (the default minContains is 1).
  • minContains: n → at least n elements match.
  • maxContains: n → at most n elements match.

The converter maps a JSON array with contains/minContains/maxContains onto these constraints. Note that contains counts matches, whereas items (stabilize_each()) constrains every element; the two are independent and can co-occur.

Behavior

  • An element "matches" spec when it would coerce/validate without error (Postel's law), reusing the same machinery stabilize_*_of() uses to run a spec.
  • Report the matching count and the required bounds in the error message; where feasible, report the locations of matches, coordinated with the .stop_incompatible() locations work described in Include locations object in conditions for element-wise failures #274.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    JSON schemanecessary for JSON schema supportmeta-stabilizers`stabilize_any_of()` etc

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions