I am new to sml, now I am trying to define a zip function which takes two lists as a tuple. here are the code. I got it working, but I have a few questions
exception Mismatch;
fun zip ([],[]) = []
| zip ((x::xs),(y::ys)) = (x, y)::zip (xs, ys)
| zip (_, _) = raise Mismatch;
Can I define the exception inside zip function, like let in end, I tried, but always get error.
Another question is for the second pattern matching, I wrote
zip ([x::xs],[y::ys]) = (x, y)::zip (xs, ys)
also gave me error.
Zip take a tuple, but each of the element is list, why can't I use [x::xs] just like other list?
last question, in pattern matching, does the order matter? I think it is, I change the order and got error, just want to make sure
Thanks
You should never define an exception inside of a let ... in ... end
*. It makes it impossible to catch it by name outside of the let
-expression.
*: It's okay if you don't plan on letting it escape from the let
-expression, but you do plan on doing that here.
As for your other question:
When you write [...]
, the SML compiler understands it as "The list containing ...
."
E.g, [1]
is the list containing 1
, [4, 6, 2]
is the list containing 4
, 6
and 2
, and so on.
When you write x :: xs
, the SML compiler understands it as "The list starting with x
, followed by the list xs
."
E.g. 1 :: []
is the list starting with a 1, followed by the empty list, and 4 :: [6, 2]
is the list starting with a 4, followed by 6
and 2
, and so on.
Now, when you write [x :: xs]
, you're doing a combination of the two, and SML understands it as: "The list containing the list starting with x
, followed by xs
."
So, by writing [...]
rather than (...)
, you're asking for a list within another list. This is not what you want.
For your final question: Yes, order matters. Patterns are checked in top-down order. Therefore,
fun foo _ = 4
| foo 4 = 5
will always return 4
, whereas
fun foo 4 = 5
| foo _ = 4
will return 5
when given a 4
.