Search code examples
listzippattern-matchingtuplessml

Few questions about sml zip function


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


Solution

  • 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.