This is a simple "try to take values on the left, but fall back to the right if they are not available" operator. It is inspired by SQL coalesce and the notation is designed to evoke the idea of testing and the C# ?? null coalescing operator. NA and NULL are treated roughly equally: both are replaced regardless of available replacement value (with some exceptions). The exceptions are: if the left hand side is a non-zero length vector we preserve the vector type of the left-hand side and do not assign any values that vectors can not hold (NULLs and complex structures) and do not replace with a right argument list.

coalesce(coalesce_left_arg, coalesce_right_arg)

coalesce_left_arg %?% coalesce_right_arg

Arguments

coalesce_left_arg

vector or list.

coalesce_right_arg

vector or list.

Value

coalesce_left_arg with NA elements replaced.

Details

This operator represents a compromise between the desire to replace length zero structures and NULL/NA values and the desire to preserve the first argument's structure (vector versus list). The order of operations has been chosen to be safe, convenient, and useful. Length zero lists are not treated as NULL (which is consistent with R in general). Note for non-vector operations on conditions we recommend looking into isTRUE, which solves some problems even faster than coalesce style operators.

When length(coalesce_left_arg)<=0 then return coalesce_right_arg if length(coalesce_right_arg)>0, otherwise return coalesce_left_arg. When length(coalesce_left_arg)>0: assume coalesce_left_arg is a list or vector and coalesce_right_arg is a list or vector that is either the same length as coalesce_left_arg or length 1. In this case replace NA/NULL elements of coalesce_left_arg with corresponding elements of coalesce_right_arg (re-cycling coalesce_right_arg when it is length 1).

Functions

  • %?%: coalesce operator

Examples

c(NA, NA, NA) %?% 5 # returns c(5, 5, 5)
#> [1] 5 5 5
c(1, NA, NA) %?% list(5) # returns c(1, 5, 5)
#> [1] 1 5 5
c(1, NA, NA) %?% list(list(5)) # returns c(1, NA, NA)
#> [1] 1 NA NA
c(1, NA, NA) %?% c(NA, 20, NA) # returns c(1, 20, NA)
#> [1] 1 20 NA
NULL %?% list() # returns NULL
#> NULL
NULL %?% c(1, NA) # returns c(1, NA)
#> [1] 1 NA
list(1, NULL, NULL) %?% c(3, 4, NA) # returns list(1, 4, NA_real_)
#> [[1]] #> [1] 1 #> #> [[2]] #> [1] 4 #> #> [[3]] #> [1] NA #>
list(1, NULL, NULL, NA, NA) %?% list(2, NULL, NA, NULL, NA) # returns list(1, NULL, NA, NULL, NA)
#> [[1]] #> [1] 1 #> #> [[2]] #> NULL #> #> [[3]] #> [1] NA #> #> [[4]] #> NULL #> #> [[5]] #> [1] NA #>
c(1, NA, NA) %?% list(1, 2, list(3)) # returns c(1, 2, NA)
#> [1] 1 2 NA
c(1, NA) %?% list(1, NULL) # returns c(1, NA)
#> [1] 1 NA
# list() %?% list(1, NA, NULL) # throws an error. c() %?% list(1, NA, NULL) # returns list(1, NA, NULL)
#> [[1]] #> [1] 1 #> #> [[2]] #> [1] NA #> #> [[3]] #> NULL #>
c() %?% c(1, NA, 2) # returns c(1, NA, 2)
#> [1] 1 NA 2