Match: Match Value Against Multiple Values

Description Usage Arguments Details Value Examples

View source: R/match.R

Description

Functional programming style matching using -> to separate conditions from associated return values.

Usage

1
Match(x, ...)

Arguments

x

object to match

...

conditions used for matching, separated from the returned value by ->. Multiple conditions can be associated with the same return value using |. Each matching statement must be separated by a comma. See "Details" below. Use . to represent the default *(else ...)* condition.

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
## 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"
)

matchr documentation built on Sept. 9, 2021, 5:07 p.m.

Related to Match in matchr...