2012-02-16 3 views
4

У меня есть список списков, например [[1; 2; 3]; [2]; [3; 4; 5; 6]; [7; 8; 9; 10] Я хочу поместить их в Hashtbl, где ключ - это длина списка, а значение - список списков, содержащий все подсписки данной длины.Ошибка Ocaml с оператором if

Таким образом, для примера выше хэша будет выглядеть следующим образом

Key   Value 
1    [[2]] 
3    [[1;2;3]] 
4    [[3;4;5;6];[7;8;9;10]] 

Кроме того, я также пытаюсь отслеживать длину самого длинного списка, и это число является то, что возвращается функцией

Код, который выполняет следующие действия.

let hashify lst = 
    let hash = Hashtbl.create 123456 in 
     let rec collector curmax lst = 
      match lst with 
        [] -> curmax 
       | h::t -> let len = (List.length h) in 
           (if ((Hashtbl.mem hash len)=true) 
           then (let v = (Hashtbl.find hash len) in Hashtbl.add hash len [email protected][h]) (* Line 660 *) 
           else (Hashtbl.add hash len [h])); 

           (collector (max len curmax) t) 
     in 
     collector 0 lst 
    ;; 

Теперь, когда я делаю это я получаю следующее сообщение об ошибке для кода выше

File "all_code.ml", line 600, characters 50-72: 
Error: This expression has type unit but an expression was expected of type 
    'a list 

Почему требуется Ocaml типа возврата «список и как я могу это исправить. Заранее спасибо Puneet

+1

Попробуйте лучше отстудить свой код (большинство редакторов могут помочь вам с этим) и удалить бесполезные круглые скобки (см. код Томаса). OCaml может быть красивым для чтения, если вы используете для написания только то, что необходимо. –

+0

Обратите внимание, что 'if Hashtbl.mem ... then let v = Hashtbl.find ...' является отходами (потому что 'Hashtbl' должен найти элемент дважды, один раз в' Hashtbl.mem' и один раз в 'Hashtbl.find') , и является «небезопасным» в том смысле, что позднее вы можете реорганизовать код таким образом, чтобы удалить инвариант, который вы только называете «Hashtbl.find», когда знаете ключ. 'Попробуйте Hashtbl.find ... с Not_found -> ...' быстрее и надежнее. – Ashe

ответ

4

Вы, вероятно, следует добавить скобки в ([email protected][h]), чтобы избежать иметь его разобрано как (Hashtbl.add hash len v)@[h]

И вы, вероятно, не должны проходить 123456 в Hashtbl.create, но разумное простое число, как 307 или 2017

4

Вы почти там: @ имеет более низкий приоритет, чем применяется, и, таким образом, как сказал Василий, Hashtbl.add hash len [email protected][h] разобран как (Hashtbl.add hash len v)@[h]. Более того, вы используете слишком много круглых скобок, и if ((Hashtbl.mem hash len)=true) не является необходимым подробным. Таким образом, возможно хороший способ написать функцию является:

let hashify lst = 
    let hash = Hashtbl.create 307 in 
    let rec collector curmax = function 
    | [] -> curmax 
    | h::t -> 
     let len = List.length h in 
     if Hashtbl.mem hash len then 
     let v = Hashtbl.find hash len in 
     Hashtbl.add hash len ([email protected][h]) 
     else 
     Hashtbl.add hash len [h]; 
     collector (max len curmax) t in 
    collector 0 lst 
4

Наиболее тяжелая работа по хэш-таблицы в OCaml огромно выгоды от обновления примитивно. Есть фактически две версии, которые делают разные вещи в зависимости от того, существует ли значение в таблице. Это тот, который вы хотите использовать:

(* Binds a value to the key if none is already present, and then updates 
    it by applying the provided map function and returns the new value. *) 
let update hashtbl key default func = 
    let value = try Hashtbl.find hashtbl key with Not_found -> default in 
    let value' = func value in 
    Hashtbl.remove hashtbl key ; Hashtbl.add hashtbl key value' ; value' 

С помощью этих примитивов, становится проще управлять Хеш-из-списков:

let prepend hashtbl key item = 
    update hashtbl key [] (fun list -> item :: list) 

Оттуда, пересекая список и добавляя все к хэш-таблица довольно проста:

let hashify lst = 
    let hash = Hashtbl.create 607 in 
    List.fold_left (fun acc list -> 
    let l = List.length list in 
    let _ = prepend hash l list in 
    max acc l 
) 0 lst 
Смежные вопросы