Рекурсивная функция, которая возвращает все значения в списке (в OCaml) - PullRequest
4 голосов
/ 13 января 2011

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

let rec elements list = match list with
 | [] -> []
 | h::t -> h; elements t;;

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

Ответы [ 2 ]

3 голосов
/ 13 января 2011

Ваша функция эквивалентна:

let rec elements list = 
  match list with 
    | [] -> []
    | h :: t -> elements t

Это происходит потому, что a ; b оценивает a (и отбрасывает результат), а затем оценивает и возвращает b.Очевидно, это, в свою очередь, эквивалентно:

let elements (list : 'a list) = []

Это не очень полезная функция.

Однако прежде чем пытаться решить эту проблему, пожалуйста, поймите, что объективные функции Camlвернуть только одно значение .Возврат более одного значения невозможен.

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

let my_function () = [ 1 ; 2; 3; 4 ] in (* Return four values *)
List.iter print_int (my_function ())    (* Print four values *)

Другим менее частым решением является предоставление функции и вызова.это для каждого результата:

let my_function action = 
  action 1 ;
  action 2 ;
  action 3 ;
  action 4
in
my_function print_int

Это менее гибко, но, возможно, быстрее, чем возвращение списка: списки могут быть отфильтрованы, отсортированы, сохранены ...

1 голос
/ 13 января 2011

Ваш вопрос немного запутан - вам нужна функция, которая возвращает все значения в списке.Ну, самый простой способ вернуть переменное число значений - использовать список!Возможно, вы пытаетесь эмулировать генераторы Python?OCaml не имеет ничего похожего на yield, но вместо этого обычно выполняет то же самое, «передавая» значение функции (используя iter, fold или map).

Что выв настоящее время написано эквивалентно этому в Python:

def elements(list):
    if(len(list) == 0):
        return []
    else:
        list[0]
        return elements(list[1:])

Если вы пытаетесь сделать это:

def elements(list):
    if(len(list) > 0):
        yield list[0]
        # this part is pretty silly but elements returns a generator
        for e in elements(list[1:]):
            yield e

for x in elements([1,2,3,4,5]):
    dosomething(x)

Эквивалент в OCaml будет выглядеть так:

List.iter dosomething [1;2;3;4;5]

Если вы пытаетесь определить, является ли список a подмножеством списка b (как я понял из ваших комментариев), тогда вы можете воспользоваться List.mem и List.for_all:

List.for_all (fun x -> List.mem x b) a

fun x -> List.mem x b определяет функцию, которая возвращает true, если значение x равно любому элементу в (является членом) b.List.for_all принимает функцию, которая возвращает bool (в нашем случае, функцию членства, которую мы только что определили) и список.Эта функция применяется к каждому элементу в списке.Если эта функция возвращает true для каждого значения в списке, то for_all возвращает true.

Итак, что мы сделали: для всех элементов в a проверьте, не являются ли они членами b.Если вы заинтересованы в том, как написать эти функции самостоятельно, я предлагаю прочитать исходный файл list.ml, который (при условии * nix), вероятно, находится в / usr / local / lib / ocaml или /usr/lib/ocaml.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...