realworldocaml/book

As-Pattern Really Needed?

mkohlhaas opened this issue · 6 comments

https://github.com/realworldocaml/book/tree/master/book/lists-and-patterns#terser-and-faster-patterns

# let rec remove_sequential_duplicates list =
    match list with
    | [] | [_] as l -> l
    | first :: (second :: _ as tl) when first = second ->        (* is this as-pattern really needed? *)
      remove_sequential_duplicates tl
    | first :: tl -> first :: remove_sequential_duplicates tl;;
val remove_sequential_duplicates : int list -> int list = <fun>

There is no cons operation on the tail. So it's not needed, I guess.

Ya, it's needed, because tl is then immediately used in the call remove_sequential_duplicates tl. Well, of course, here you could just use List.tl, but because this chapter talks about patterns it's more instructive to use a pattern instead.

Does that mean you need as patterns everywhere? Like e.g. in the last match?

Nay, - it's not required to use as unless you want to capture a composite* piece of a match in a variable.

*I mean something like: second :: _ as tl - where tl now stores the sublist matched by: second :: _

Why not ...

# let rec remove_sequential_duplicates list =
    match list with
    | [] | [_] as l -> l
    | first :: second :: tl when first = second ->        (* isn't this the same? *)
      remove_sequential_duplicates tl
    | first :: tl -> first :: remove_sequential_duplicates tl;;
val remove_sequential_duplicates : int list -> int list = <fun>

Nay, alas it's not the same. It would be the same if you re-wrote code like this:

    | first :: second :: tl when first = second ->
      remove_sequential_duplicates (second :: tl)        (* same *)

Otherwise, a call like remove_sequential_duplicates [1; 1] would yield an incorrect result [], instead of the correct one: [1].

Okay! Now I understand! Thanks!