From e368e421d22b4b4fbb2f64f62dd9b72c0e327976 Mon Sep 17 00:00:00 2001 From: Raghav <***> Date: Sun, 16 Jun 2024 00:50:53 -0600 Subject: [PATCH 1/6] Add examples of list matching in roc examples --- examples/List/README.md | 21 +++++++++++++++++++++ examples/List/main.roc | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 examples/List/README.md create mode 100644 examples/List/main.roc diff --git a/examples/List/README.md b/examples/List/README.md new file mode 100644 index 00000000..04c4d350 --- /dev/null +++ b/examples/List/README.md @@ -0,0 +1,21 @@ +# List Pattern Matching + +A Roc solution to one of the 99 Lisp problems - Find the number of elements in a list & Find an element in a list. Here we can use pattern matching on a list to count the number of elements recursively. + +## Code +```roc +file:main.roc +``` + +## Output + +Run this from the directory that has `main.roc` in it: + +``` +$ roc run +List [1,2,3,4,5,6,7,8,9,10] has a length of 10 +5 found at index 4 in the list [1,2,3,4,5,6,7,8,9,10] + +``` + +You can also use `roc test` to run the tests. diff --git a/examples/List/main.roc b/examples/List/main.roc new file mode 100644 index 00000000..35bd63d4 --- /dev/null +++ b/examples/List/main.roc @@ -0,0 +1,35 @@ +app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" } + +import pf.Stdout +import pf.Task + +listOfNumbersUpto10 = List.range { start: At 1, end: At 10 } + +main = + Stdout.line! "List $(printPrettyList listOfNumbersUpto10) has a length of $(Num.toStr(lengthOfList listOfNumbersUpto10))" + + Stdout.line! "$(findInList listOfNumbersUpto10 5 0) in the list $(printPrettyList listOfNumbersUpto10)" + +printPrettyList: List U64 -> Str +printPrettyList = \list1 -> + listToStr = List.map list1 Num.toStr + |> Str.joinWith "," + "[$(listToStr)]" + +## Find the lenght of a list +lengthOfList : List U64 -> U64 +lengthOfList = \list -> + when list is + [] -> 0 + [_, .. as tail] -> 1 + lengthOfList tail + +# Find in list +findInList: List, U64, U64 -> Str +findInList = \list, val, index -> + when list is + [] -> "$(Num.toStr val) not found" + [head, .. as tail] -> if head == val then "$(Num.toStr val) found at index $(Num.toStr index)" else findInList tail val (index+1) + +## Test Case 1: Length of an empty List & non-empty List +expect lengthOfList [] == 0 +expect lengthOfList [1,2,3] == List.len [1,2,3] From 2c5ac78c08517e6435f834913ace1cfd4fd7a824 Mon Sep 17 00:00:00 2001 From: Raghav <***> Date: Sun, 16 Jun 2024 22:53:10 -0600 Subject: [PATCH 2/6] Address feedback comments, remove finding len of list and refactor the search function --- examples/List/README.md | 2 +- examples/List/main.roc | 49 +++++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/examples/List/README.md b/examples/List/README.md index 04c4d350..1d459256 100644 --- a/examples/List/README.md +++ b/examples/List/README.md @@ -1,6 +1,6 @@ # List Pattern Matching -A Roc solution to one of the 99 Lisp problems - Find the number of elements in a list & Find an element in a list. Here we can use pattern matching on a list to count the number of elements recursively. +A Roc solution to finding an element in a list. Here we use pattern matching on a list to check if the searched element is present in the list. If the head matches we return True if not, we continue searching the tail of the list. A base case of empty list is included which will always return false. ## Code ```roc diff --git a/examples/List/main.roc b/examples/List/main.roc index 35bd63d4..89800b25 100644 --- a/examples/List/main.roc +++ b/examples/List/main.roc @@ -1,35 +1,42 @@ -app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" } +app [main] { + pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" +} import pf.Stdout import pf.Task listOfNumbersUpto10 = List.range { start: At 1, end: At 10 } +numberToSearch = 5 main = - Stdout.line! "List $(printPrettyList listOfNumbersUpto10) has a length of $(Num.toStr(lengthOfList listOfNumbersUpto10))" - - Stdout.line! "$(findInList listOfNumbersUpto10 5 0) in the list $(printPrettyList listOfNumbersUpto10)" + listOfNumbersAsString = printPrettyList listOfNumbersUpto10 + numberExists = findInList listOfNumbersUpto10 numberToSearch + if numberExists then + Stdout.line! "$(Num.toStr numberToSearch) exists in $(listOfNumbersAsString)" + else + Stdout.line! "$(Num.toStr numberToSearch) does not exist in $(listOfNumbersAsString)" printPrettyList: List U64 -> Str printPrettyList = \list1 -> - listToStr = List.map list1 Num.toStr - |> Str.joinWith "," + listToStr = + list1 + |> List.map Num.toStr + |> Str.joinWith "," "[$(listToStr)]" -## Find the lenght of a list -lengthOfList : List U64 -> U64 -lengthOfList = \list -> - when list is - [] -> 0 - [_, .. as tail] -> 1 + lengthOfList tail - # Find in list -findInList: List, U64, U64 -> Str -findInList = \list, val, index -> +findInList: List, U64 -> Bool +findInList = \list, val -> when list is - [] -> "$(Num.toStr val) not found" - [head, .. as tail] -> if head == val then "$(Num.toStr val) found at index $(Num.toStr index)" else findInList tail val (index+1) - -## Test Case 1: Length of an empty List & non-empty List -expect lengthOfList [] == 0 -expect lengthOfList [1,2,3] == List.len [1,2,3] + [] -> Bool.false + [head, .. as tail] -> + if head == val then + Bool.true + else + findInList tail val + + +## Test Case: Find the value in a list +expect findInList [1,2,3,4,5] 3 == Bool.true +expect findInList [1,2,3,4,5] 0 == Bool.false +expect findInList [] 0 == Bool.false From 67b334f103cee11fa4b562183cf50982e5553f7e Mon Sep 17 00:00:00 2001 From: Raghav <***> Date: Sun, 16 Jun 2024 22:56:39 -0600 Subject: [PATCH 3/6] Updated README with right results --- examples/List/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/List/README.md b/examples/List/README.md index 1d459256..2ad6a514 100644 --- a/examples/List/README.md +++ b/examples/List/README.md @@ -13,9 +13,7 @@ Run this from the directory that has `main.roc` in it: ``` $ roc run -List [1,2,3,4,5,6,7,8,9,10] has a length of 10 -5 found at index 4 in the list [1,2,3,4,5,6,7,8,9,10] - +5 exists in [1,2,3,4,5,6,7,8,9,10] ``` You can also use `roc test` to run the tests. From 64890825d8a1eda8c8d38237d8ed572ba6b0d49b Mon Sep 17 00:00:00 2001 From: Raghav <***> Date: Sun, 16 Jun 2024 23:31:35 -0600 Subject: [PATCH 4/6] Linter errors --- examples/List/main.roc | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/examples/List/main.roc b/examples/List/main.roc index 89800b25..866756c2 100644 --- a/examples/List/main.roc +++ b/examples/List/main.roc @@ -1,5 +1,5 @@ app [main] { - pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" + pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br", } import pf.Stdout @@ -16,27 +16,26 @@ main = else Stdout.line! "$(Num.toStr numberToSearch) does not exist in $(listOfNumbersAsString)" -printPrettyList: List U64 -> Str +printPrettyList : List U64 -> Str printPrettyList = \list1 -> - listToStr = - list1 - |> List.map Num.toStr - |> Str.joinWith "," - "[$(listToStr)]" + listToStr = + list1 + |> List.map Num.toStr + |> Str.joinWith "," + "[$(listToStr)]" # Find in list -findInList: List, U64 -> Bool +findInList : List, U64 -> Bool findInList = \list, val -> when list is [] -> Bool.false [head, .. as tail] -> - if head == val then - Bool.true - else - findInList tail val - + if head == val then + Bool.true + else + findInList tail val ## Test Case: Find the value in a list -expect findInList [1,2,3,4,5] 3 == Bool.true -expect findInList [1,2,3,4,5] 0 == Bool.false -expect findInList [] 0 == Bool.false +expect findInList [1, 2, 3, 4, 5] 3 == Bool.true +expect findInList [1, 2, 3, 4, 5] 0 == Bool.false +expect findInList [] 0 == Bool.false From 11ac2d528d3a936b693d8f61d1477fdd0cbb277c Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 22 Jun 2024 16:56:44 +0200 Subject: [PATCH 5/6] Add as to pattern matching example --- examples/List/README.md | 19 --------- examples/List/main.roc | 41 -------------------- examples/PatternMatching/PatternMatching.roc | 40 ++++++++++++------- examples/PatternMatching/README.md | 28 +++++++++++-- examples/index.md | 2 +- 5 files changed, 52 insertions(+), 78 deletions(-) delete mode 100644 examples/List/README.md delete mode 100644 examples/List/main.roc diff --git a/examples/List/README.md b/examples/List/README.md deleted file mode 100644 index 2ad6a514..00000000 --- a/examples/List/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# List Pattern Matching - -A Roc solution to finding an element in a list. Here we use pattern matching on a list to check if the searched element is present in the list. If the head matches we return True if not, we continue searching the tail of the list. A base case of empty list is included which will always return false. - -## Code -```roc -file:main.roc -``` - -## Output - -Run this from the directory that has `main.roc` in it: - -``` -$ roc run -5 exists in [1,2,3,4,5,6,7,8,9,10] -``` - -You can also use `roc test` to run the tests. diff --git a/examples/List/main.roc b/examples/List/main.roc deleted file mode 100644 index 866756c2..00000000 --- a/examples/List/main.roc +++ /dev/null @@ -1,41 +0,0 @@ -app [main] { - pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br", -} - -import pf.Stdout -import pf.Task - -listOfNumbersUpto10 = List.range { start: At 1, end: At 10 } -numberToSearch = 5 - -main = - listOfNumbersAsString = printPrettyList listOfNumbersUpto10 - numberExists = findInList listOfNumbersUpto10 numberToSearch - if numberExists then - Stdout.line! "$(Num.toStr numberToSearch) exists in $(listOfNumbersAsString)" - else - Stdout.line! "$(Num.toStr numberToSearch) does not exist in $(listOfNumbersAsString)" - -printPrettyList : List U64 -> Str -printPrettyList = \list1 -> - listToStr = - list1 - |> List.map Num.toStr - |> Str.joinWith "," - "[$(listToStr)]" - -# Find in list -findInList : List, U64 -> Bool -findInList = \list, val -> - when list is - [] -> Bool.false - [head, .. as tail] -> - if head == val then - Bool.true - else - findInList tail val - -## Test Case: Find the value in a list -expect findInList [1, 2, 3, 4, 5] 3 == Bool.true -expect findInList [1, 2, 3, 4, 5] 0 == Bool.false -expect findInList [] 0 == Bool.false diff --git a/examples/PatternMatching/PatternMatching.roc b/examples/PatternMatching/PatternMatching.roc index f55b5f25..b056b760 100644 --- a/examples/PatternMatching/PatternMatching.roc +++ b/examples/PatternMatching/PatternMatching.roc @@ -34,34 +34,34 @@ expect expect match = \input -> when input is - [.., 42] -> EndWith42 + [.., 42] -> EndsWith42 _ -> Other - (match [24, 64, 42] == EndWith42) - && (match [42, 1, 5] != EndWith42) + (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, ..] -> FooBar + [Foo, Bar, ..] -> StartsWithFooBar _ -> Other - (match [Foo, Bar, Bar] == FooBar) - && (match [Bar, Bar, Foo] != FooBar) + (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"] -> Bingo + [Foo, Bar, Baz "Hi"] -> FooBarBazStr _ -> Other - (match [Foo, Bar, Baz "Hi"] == Bingo) - && (match [Foo, Bar] != Bingo) - && (match [Foo, Bar, Baz "Hi", Blah] != Bingo) + (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, @@ -69,9 +69,21 @@ expect expect match = \input -> when input is - [Foo, Count num, ..] if num > 0 -> FooBar + [Foo, Count num, ..] if num > 0 -> FooCountIf _ -> Other - (match [Foo, Count 1] == FooBar) - && (match [Foo, Count 0] != FooBar) - && (match [Baz, Count 1] != FooBar) + (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) diff --git a/examples/PatternMatching/README.md b/examples/PatternMatching/README.md index b0bfd3d4..b550d404 100644 --- a/examples/PatternMatching/README.md +++ b/examples/PatternMatching/README.md @@ -1,6 +1,28 @@ -# Pattern Matching +# Pattern Matching on Lists -Some different ways to do pattern matching in Roc. +All the ways to pattern match on lists: +```roc +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 ```roc @@ -14,5 +36,5 @@ Run this from the directory that has `PatternMatching.roc` in it: ``` $ roc test PatternMatching.roc -0 failed and 7 passed in 629 ms. +0 failed and 8 passed in 88 ms. ``` diff --git a/examples/index.md b/examples/index.md index fbbe3149..c0bf5576 100644 --- a/examples/index.md +++ b/examples/index.md @@ -8,7 +8,7 @@ You can find the source code for all of these at [github.com/roc-lang/examples]( - [FizzBuzz](/FizzBuzz/README.html) - [Basic Dict Usage](/BasicDict/README.html) - [Tuples](/Tuples/README.html) -- [Pattern Matching](/PatternMatching/README.html) +- [Pattern Matching on Lists](/PatternMatching/README.html) - [Tasks & Error Handling](/Tasks/README.html) - [Import Files](/IngestFiles/README.html) - [Import from Directory](/ImportFromDirectory/README.html) From 8a81e76f923ac4f75404c0650ae81dfc2c4261e0 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sat, 22 Jun 2024 16:58:39 +0200 Subject: [PATCH 6/6] format --- examples/PatternMatching/PatternMatching.roc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/PatternMatching/PatternMatching.roc b/examples/PatternMatching/PatternMatching.roc index b056b760..c2251488 100644 --- a/examples/PatternMatching/PatternMatching.roc +++ b/examples/PatternMatching/PatternMatching.roc @@ -76,7 +76,7 @@ expect && (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 `..` +# Use `as` to create a variable equal to the part of the list that matches `..` expect match = \input -> when input is