Skip to content

Conversation

@DavisVaughan
Copy link
Member

This effectively freezes case_match()'s implementation in preparation for it to be superseded by recode_values().

This removes the final usage of dplyr:::vec_case_when() outside of case_when() itself, which will come next, allowing us to delete that dplyr helper entirely.

Comment on lines +171 to +175
if (length(haystacks) == 0L) {
# `case_match()` is like `case_when()` and doesn't allow empty `...`,
# even though `vec_case_when()` is well defined for this case.
abort("At least one condition must be supplied.", call = call)
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike dplyr:::vec_case_when(), vctrs::vec_case_when() is well defined when you don't give it any inputs. It's useful for programmatic reasons.

But case_when() and case_match() don't support this since we don't want to expose the unspecified type to normal users.

So I've recreated the dplyr:::vec_case_when() error here.

library(vctrs)

vec_case_when(
  cases = list(),
  values = list()
)
#> <unspecified> [0]

vec_case_when(
  cases = list(),
  values = list(),
  size = 2
)
#> <unspecified> [2]

vec_case_when(
  cases = list(),
  values = list(),
  default = 1L
)
#> integer(0)

vec_case_when(
  cases = list(),
  values = list(),
  ptype = integer()
)
#> integer(0)

Condition
Error in `case_match()`:
! Can't combine `..1 (right)` <integer> and `.default` <character>.
! Can't combine <integer> and `.default` <character>.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike with if_else(), we are going to have to accept this new error message where you don't have the label.

Essentially we need the common type of list_of_rhs and default, which we do at C level via

ptype <- vec_ptype_common(!!!list_of_rhs)
ptype <- vec_ptype2(ptype, default, y_arg = default_arg)

https://github.com/r-lib/vctrs/blob/c46809139a63699bde2f1b4b58286553c2f2075e/src/list-combine.c#L1769-L1823

There is no easy way to smush default (and default_arg) into the list_of_rhs at the C level compute the common ptype all in one shot. This computation actually takes place in list_combine(), where the list_of_rhs could be a very large list of objects we want to combine, so allocating a list of size + 1 just to insert default isn't worth it.

Comment on lines 126 to +127
Error in `vec_case_match()`:
! `values[[1]]` must have size 1, not size 2.
! Can't recycle `values[[1]]` (size 2) to size 1.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is actually more correct. We are recycling each value here to the size of x.

@DavisVaughan DavisVaughan merged commit c0aebf0 into main Oct 2, 2025
14 checks passed
@DavisVaughan DavisVaughan deleted the feature/case-match-on-vctrs-case-when branch October 2, 2025 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants