Match {matchr} | R Documentation |
Match Value Against Multiple Values
Description
Functional programming style matching using ->
to separate
conditions from associated return values.
Usage
Match(x, ...)
Arguments
x |
object to match |
... |
conditions used for matching, separated from the returned
value by |
Details
Unlike switch
, Match
accepts a variety of
different condition statements. These can character, numeric,
or logical values, functions, symbols, language objects, enums,
etc. For example, "hello" -> 1
tests whether the object is
equal to "hello"
. If so, the function returns 1
,
otherwise the next condition is tested. <-
can also be used.
If so, the condition & return expression are reversed: 1 <- "hello"
also tests "hello"
and returns 1
.
Each condition is tested sequentially by calling the appropriate method
of match_cond
. If the condition is a character value, then
match_cond.character
is called, and so on. If a match is
confirmed, the right-hand side is evaluated and returned.
For atomic vectors - numeric, logical, or character - Match
will
check for equality. All resulting values must be TRUE
to match.
Lists and environments are checked using identical
. If a
function is placed within the condition, then the function will be evaluated
on object x
. If the result is logical and TRUE
, then it is
considered a match. A non-logical result will be checked again using
match_cond
. Failed function calls with an error are treated
as a non-match rather than stopping Match
. Expressions are evaluated
similar to functions.
The period .
is a special condition in Match
. When alone,
it is treated as the "default" condition that always matches. When used
as a call, though, it matches values within object x
and/or attaches
the individual items within x
for use in the return expression.
For example, x = c(1, 2)
will be matched with the condition
.(1, second)
. This is because the first values are identical
(1 == 1)
. Furthermore, second = 2
for use in the return
expression. Preface a symbol with ..
to evaluate it and check
for equality. ...
can be used to denote any number of unspecified
objects.
The period call .()
can also be used to test named member of x
,
though all objects in .()
must be named to do so. For example, the
condition .(a = 5, b=)
tests whether x
contains "a"
with a value of 5
and "b"
with any value.
If function(...)
is used on the left hand side, then it may
need to be surrounded by parentheses for the parser to properly recognize
it. The %fn%
infix function has be provided as syntactic sugar
for developing functions for matching.
Similar to many functional languages, (first:rest)
can be used
as a condition to extract the first element and the rest from any
vector as long as the vector is sufficiently long. Variables used on the
left hand side can be called on the right hand side expression.
Matching an Enum
causes symbols to represent possible
variants. For example, None -> "none"
would try to match the
variant of x
with None
. If it succeeds, then Match
will return "none"
. A function call on the left-hand side for an
Enum is treated as a variant and its inside arguments, which are made
available in the result expression. So, Some(var) -> sqrt(var)
would
attempt to match on the variant Some
. If it matches, then the
inside is exposed as the variable var
for the right-hand side to
use. The number of objects in the variant on the left-hand side must
match the number of objects inside of x
or else an error will
populate.
Regex conditions can be used when matching strings by surrounding the
expression in braces. For example, the condition "[ab]*" is equivalent
to using grepl("\[ab\]*", ...)
. The braces must be the first and
last characters to trigger a regex match.
Call fallthrough
within a return expression to stop evaluating
the expression and return to matching. This can be convenient for complex
matching conditions or to execute code for side-effects, such as printing.
Value
an object based on the matched clause. An Error is produced if no match is found.
Examples
## Matching to functions, characters, regex, and default
Match(
"abc",
is.numeric -> "Not a character!",
is.character -> {
print("Found a character!")
fallthrough()
},
"a" | "b" | "c" -> "It's a letter!",
"{bc}" -> "Contains 'bc'!",
. -> "Can be anything!"
)
## Unwrapping a Result enum
val <- Result$Ok("hello world!")
Match(
val,
Ok(w) -> w,
Err(s) -> s
)
## Using functions
# If 'function' is used on the lhs, surround in '()'
# Alternatively, use %fn% notation
Match(
1:10,
(function(i) mean(i) < 5) -> TRUE,
i %fn% (mean(i) >= 5) -> FALSE
)
## Extracting parts
x <- list(a = 5, b = 6, c = 7)
Match(
x,
.(a=, d=2) -> "won't match, no 'd'",
.(a=5, b=) -> "will match, a == '5'",
(x:xs) -> {
print(x) # 5
print(xs) # list(b=6, c=7)
"will match, since not empty"
},
. -> "this matches anything!"
)
z <- c(1,2,3,4)
first <- 1
Match(
z,
.(0, ...) -> "no match, first is 1 not 0",
.(1, 2) -> "no match, z has 4 elements",
.(x, 2, ...) -> paste("match, x = ", x),
.(..first, ...) -> "match, since 'first' == 1"
)