Pattern Matching

With pattern matching, programmers can express perplexing conditional expressions in a comprehensive way. It alleviates the hell of mind-blowing nested if conditionals and provides a way to destructure matched values at the same time.

Introduction

The match expressions implement pattern matching in Cloe. Note that match keyword is not a name of a function but a special keyword to begin writing such expressions.

(match someNumber
  1 "odd"
  2 "even"
  3 "odd")

The result of the expression above depends on the value of num as it will be "odd" if num == 1, "even" if 2, and "odd" if 3. When no patterns are matched with the given values, the expressions throw errors.

Wildcard patterns

When you need to capture some values which can take any kinds of values in match expressions, wildcard patterns would help you. These patterns bind matched values to given names so that they can be used inside the corresponding expressions.

(match someString
  "foo" "Yes!"
  "bar" "OK!"
  x     (merge "No way, " x "..."))

List patterns

Lists can be also matched in match expressions while there are some extra features about them. Firstly, you can use wildcard patterns inside list patterns to capture their elements. And that rule is applied in a recursive way as even elements in a list in another list can be referred to. Secondly, there is another kind of pattern preceded by .. with which you can put remaining elements in a list together into a variable.

(match someList
  []                        "Empty!"
  [1 2 3]                   "1, 2, and 3!"
  [x y z]                   (+ x y z)
  ["foo" "bar" ..rest]      rest
  [[1 2 3] [4 5 6] [7 8 x]] (merge (toString x) " should be 9."))

Dictionary patterns

Dictionary patterns are quite similar to list patterns as they can be combined with wildcard and rest patterns. However, there is a catch that dictionary keys are not allowed to be wildcard patterns but only values.

(match someDictionary
  {}                          "Empty!"
  {"foo" 1 "bar" 2}           "Foo!"
  {"dividend" x "divisor" y}  (/ x y)
  {"foo" 42 "bar" nil ..rest} rest)