2012-03-20 2 views
7

Я новичок в Ocaml, просто хочу убедиться, как выполнить простую функцию, такую ​​как возврат n-го элемента списка с помощью рекурсивной функции?возвращает n-й элемент списка в OCaml?

Прототип как get_nth (list, n) с int list * int -> int

, например get_nth ([1,2,3], 1) -> 2

Спасибо

+1

Это действительно звучит как домашняя проблема. Это поможет, если вы продемонстрируете какой-то код, который вы пробовали, который работает не так, как вы надеялись. –

ответ

11

Вы можете не заметить, но List.nth функция уже существует в List module.

Если вы хотите написать его с помощью рекурсии:

let rec get_nth = function 
    | [], _ -> raise (Failure "get_nth") 
    | _, n when n < 0 -> raise (Invalid_argument "get_nth") 
    | x::_, 0 -> x 
    | x::xs, n -> get_nth(xs, n-1) 
+0

@VictorNicollet: Спасибо за редактирование. – pad

4

Использование кортежей в качестве параметров, как это не является общим в OCaml. Обычно вы будете использовать каррирование и определить свою функцию, как это:

let get_nth list n = ... 

Это будет иметь подпись 'a list -> int -> 'a. Также обратите внимание, что здесь у вас есть параметр 'a, а это означает, что нет никаких оснований ограничивать вашу функцию только одним.

Теперь давайте рассмотрим проблему. Если вы хотите получить нулевой элемент, как бы выглядела ваша функция?

let get_nth list 0 = List.head list (* this is not actually valid in OCaml *) 

теперь, если у вас есть функция, чтобы получить п-й элемент из списка м элементов (NB п> т), как вы могли бы использовать эту функцию, чтобы построить еще одну функцию, которая получит это п + первый элемент из список m + 1 элементов? Пусть эта функция для п + 1 элементов быть get_nth'

let get_nth' list n' = get_nth (List.tail list) (n'-1) 

Теперь все, что вам нужно сделать, это объединить два, и вы сделали. Я оставлю эту последнюю часть тебе.

Если вы последуете этому совету, вы получите нечто более сложное, чем это должно быть. Однако легче понять, что происходит в этом направлении.

+0

К сожалению, я боюсь, что ваша попытка более запутанна, чем должна быть. Совместимость шаблонов Ocaml довольно визуально объяснительна сама по себе. – PieOhPah

3

(На мой взгляд) Более простое решение без использования кортеж может быть:

let rec get_nth mylist index = match mylist with 
    | [] -> raise (Failure "empty list") 
    | first::rest -> 
     if index = 0 then first 
     else get_nth rest (index-1) 
;; 
+1

Я бы сделал правильный ответ. Использование кортежа в качестве аргумента в функции Ocaml не очень идиоматично и требует выделения. – PieOhPah

0

Я прочитал here, что с помощью Result вместо повышения ошибки может быть лучше, так как вам не нужно использовать try ... with. (Код редактируется @Omar Mahili)

let rec get_nth mylist index = match mylist with 
    | [] -> Error "empty list" 
    | first::rest -> 
     if index = 0 then Ok first 
     else get_nth rest (index-1) 
;; 

let result [1; 2; 3] 2 in 
    match result with 
    | Error reason -> print_string reason 
    | Ok num -> print_int num 
;; 

Result является частью Core.Std, если я правильно.

Смежные вопросы