2011-01-13 2 views
4

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

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

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

ответ

3

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

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 

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

+0

Благодарим за отзыв. Я думал об этом в два этапа с двумя функциями, как вы описали, но моя проблема заключается в том, чтобы каждый из них извлекал каждый элемент. Я должен быть немного более конкретным. Моя основная функция - это функция подмножества, в которой мне задана задача определить, является ли список a подмножеством списка b. Я должен написать эту функцию способом, который является полиморфным, но сейчас я могу только выяснить, как это сделать со списком int. – Atticus

+0

Проблема в том, что я написал функцию, чтобы вернуть первый элемент списка: let head list = match list с h :: t -> h | [] -> 0. Поскольку я должен учитывать пустой список, я возвращаю 0, а OCaml определяет, что эта функция принимает список int. Поскольку функция подмножества должна быть полиморфной, я не могу заранее знать, что нужно возвращать для пустого множества, будь то 0, «null» или что угодно. Поэтому это ограничивает меня списками ints. – Atticus

+0

в этом случае (что нужно вернуть для пустого списка), просто поднимите ошибку: (с ошибкой «ошибка») – gasche

1

Ваш вопрос вроде запутанным - вы хотите функцию который возвращает все значения в списке. Ну, самый простой способ вернуть переменное количество значений - это список! Возможно, вы пытаетесь подражать генераторам 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 определяет функцию, которая возвращает истину, если значение х равно любому элементу (является членом) б. List.for_all выполняет функцию, которая возвращает bool (в нашем случае, только функцию определения членства) и список. Он применяет эту функцию к каждому элементу в списке. Если эта функция возвращает true для каждого значения в списке, то for_all возвращает true.

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

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