вернуть n-й элемент списка в OCaml? - PullRequest
8 голосов
/ 21 марта 2012

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

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

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

Спасибо

Ответы [ 4 ]

13 голосов
/ 21 марта 2012

Вы можете не заметить, но функция List.nth уже есть в Модуль списка .

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

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)
5 голосов
/ 21 марта 2012

Использование кортежей в качестве таких параметров не является обычным явлением в 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 *)

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

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

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

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

3 голосов
/ 21 мая 2014

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

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)
;;
0 голосов
/ 21 сентября 2017

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

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, если я прав.

...