1
votes

I've written this mergesort implementation, which works fine if I put the divide function outside of the mergesort function. But when I try to make divide an inner function of mergesort I encounter a syntax error.

I know, there must be some really simple explanation for this. I've looked all over the internet, yet found nothing.

Here is the code:

let mergesort list = 
  let rec sort lists acc = (
    let rec merge sublist1 sublist2 merged_list =
    match sublist1 with
      |[] -> merged_list @ sublist2
      |hd1 :: tl1 -> 
        match sublist2 with
          |[] -> merged_list @ sublist1
          |hd2 :: tl2 -> 
            if hd1 < hd2 then merge tl1 sublist2 (merged_list @ hd1::[])
            else merge sublist1 tl2 (merged_list @ hd2::[])
    in match lists with 
      |[] -> 
        (match acc with
          |[] -> []
          |hd :: [] -> hd
          |_ -> sort acc [])
      |hd :: tl -> sort (List.tl tl) ((merge (List.hd tl) hd [])::acc)  
  )
  and rec divide list list_of_lists = (
    match list with
      [] -> list_of_lists
      |hd :: tl -> divide tl ((hd :: []) :: list_of_lists)
  )
  in sort (divide list []) []
;; 

and it results into:

Characters 567-570:
and rec divide list list_of_lists = (
    ^^^
Error: Syntax error
2
Did you try removing the rec keyword that the error is telling you to? and will repeat the previous definition, which is in this case let rec, so you’re effectively writing let rec rec - Nick Zuber

2 Answers

2
votes

A local definition has the following syntax in OCaml:

let [rec] pattern1 =  expr1 and … and  patternN =  exprN in expr

Thus an extra rec is not allowed after the and keyword, and is allowed only after the first let. The rec flag extends to all values defined in the local definition, thus you just need to remove this erroneous rec after and.

1
votes

You need to simply remove the rec keyword from your definition there.

This is because when you use the and keyword, you’re effectively repeating the previous definition syntactically, which in this case is let rec.

So your current implementation is effectively the same as saying let rec rec