octref
octref

Reputation: 6801

Why does pattern with variable not match?

I'm writing a code that can find the median of a list, and I cannot use rec and should use List.fold_left/right. I wrote the following code, which should work.

It finds the length of the list, if it's an odd number like 5, then it sets len1, len2 to 2, 3, if it's an even number like 6, then it sets len1, len2 to 2, 3.

Then for each member in the list I match the number of those elements that are less than it.
However, the following pattern matching always math lessNum elmt to len1 - can someone tell me why it is so?

let median (lst : int list) : float option =
  let len = List.length lst in
  if lst = [] then None
  else 
    let len1, len2 = (len - 1) / 2, (len + 1) / 2 in
    let lessNum a =
      List.length (List.find_all (fun n -> n < a) lst) in 
    let answer = List.fold_left (fun accm elmt -> 
      match (lessNum elmt) with 
        | len1 -> accm + elmt
        | len2 -> failwith "len2"
        | _ -> failwith "other"
) 0 lst in
    if len mod 2 = 0 
    then Some ((float_of_int answer) /. 2.0)
    else Some (float_of_int answer)

Upvotes: 2

Views: 115

Answers (1)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66823

An identifier appearing in a pattern always matches, and binds the corresponding value to the identifier. Any current value of the identifier doesn't matter at all: the pattern causes a new binding, i.e., it gives a new value to the identifier (just inside the match).

# let a = 3;;
val a : int = 3
# match 5 with a -> a;;
- : int = 5
# a;;
- : int = 3
#

So, your match statement isn't doing what you think it is. You'll probably have to use an if for that part of your code.

Update

Here's how to use an association list to approximate the function f in your followup question:

let f x = List.assoc x [(pat1, ans1); (pat2, ans2)]

This will raise a Not_found exception if x is not equal to pat1 or pat2.

(I think your Python code is missing return.)

Upvotes: 4

Related Questions