Pattern Matching on Lists
All the ways to pattern match on lists:
when input is [] -> EmptyList [_, ..] -> NonEmptyList ["Hi", ..] -> StartsWithHi [.., 42] -> EndsWith42 [Foo, Bar, ..] -> StartsWithFooBar [Foo, Bar, Baz "Hi"] -> FooBarBazStr [Foo, Count num, ..] if num > 0 -> FooCountIf [head, .. as tail] -> HeadAndTail head tail _ -> Other
Note that this specific snippet would not typecheck because it uses lists of different types. This is just meant to be a compact overview. See the code section below for valid Roc.
Code
module [] # Match an empty list expect match = \input -> when input is [] -> EmptyList _ -> Other (match [] == EmptyList) && (match [A, B, C] != EmptyList) # Match a non-empty list expect match = \input -> when input is [_, ..] -> NonEmptyList _ -> Other (match [A, B, C] == NonEmptyList) && (match [] != NonEmptyList) # Match a list whose first element is the string "Hi" expect match = \input -> when input is ["Hi", ..] -> StartsWithHi _ -> Other (match ["Hi", "Hello", "Yo"] == StartsWithHi) && (match ["Hello", "Yo", "Hi"] != StartsWithHi) # Match a list whose last element is the number 42 expect match = \input -> when input is [.., 42] -> EndsWith42 _ -> Other (match [24, 64, 42] == EndsWith42) && (match [42, 1, 5] != EndsWith42) # Match a list that starts with a Foo tag # followed by a Bar tag expect match = \input -> when input is [Foo, Bar, ..] -> StartsWithFooBar _ -> Other (match [Foo, Bar, Bar] == StartsWithFooBar) && (match [Bar, Bar, Foo] != StartsWithFooBar) # Match a list with these exact elements: # Foo, Bar, and then (Baz "Hi") expect match = \input -> when input is [Foo, Bar, Baz "Hi"] -> FooBarBazStr _ -> Other (match [Foo, Bar, Baz "Hi"] == FooBarBazStr) && (match [Foo, Bar] != FooBarBazStr) && (match [Foo, Bar, Baz "Hi", Blah] != FooBarBazStr) # Match a list with Foo as its first element, and # Count for its second element. Count holds a number, # and we only match if that number is greater than 0. expect match = \input -> when input is [Foo, Count num, ..] if num > 0 -> FooCountIf _ -> Other (match [Foo, Count 1] == FooCountIf) && (match [Foo, Count 0] != FooCountIf) && (match [Baz, Count 1] != FooCountIf) # Use `as` to create a variable equal to the part of the list that matches `..` expect match = \input -> when input is [head, .. as tail] -> HeadAndTail head tail _ -> Other (match [1, 2, 3] == HeadAndTail 1 [2, 3]) && (match [1, 2] == HeadAndTail 1 [2]) && (match [1] == HeadAndTail 1 []) && (match [] == Other)
Output
Run this from the directory that has PatternMatching.roc
in it:
$ roc test PatternMatching.roc 0 failed and 8 passed in 88 ms.