I recently learned that Nim has pattern matching through the fusion/matching library. I was trying to make this OCaml example in Nim:
let rec sum = function
| [] -> 0
| head :: tail -> head + (sum tail)
This is what I came up with:
import fusion/matching
{.experimental: "caseStmtMacros".}
func sum(arr: openarray[int]): int =
case arr:
of []:
0
of [@head, all @tail]:
head + (sum tail)
echo (sum [1, 2, 3, 4])
However, I get a compile error:
/home/rainbow/test.nim(5, 3) template/generic instantiation of `match` from here
/home/rainbow/.nimble/pkgs/fusion-1.0/fusion/matching.nim(2339, 13) Error: invalid type: 'openArray[int]' for let
Is this just a bug or am I doing something wrong?A little something like this works:
import fusion/matching
{.experimental: "caseStmtMacros".}
func sum(arr: seq[int]): int =
case arr:
of [@head, all @tail]:
head + (sum tail)
else: 0
echo (sum @[1, 2, 3, 4])
Nim is not Ocaml and splitting up a seq into (head, tail) sections is slow and not idiomatic code. Instead use:
func sum(arr: openarray[int]): int =
result = 0
for a in arr: result += a
echo sum([1, 2, 3, 4])
For this case. Pattern matching can be useful in other cases, of course.
splitting up a seq into (head, tail) sections is slow
Does this include using list splices too?
func sum(arr: seq[int]): int =
if arr == @[]:
0
else:
arr[0] + (sum arr[1..^1])
I was trying to make this OCaml example in Nim:
If it doesn't have to be the same as OCaml examle, you can use the built-in sum proc.
And if you want to do it yourself, I would do it the same way the above function is implemented, i.e. use for-loop.