OCaml: перебирая список и пропуская элементы, если неправильный конструктор - PullRequest
2 голосов
/ 30 сентября 2011

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

Вот моя цель:

Я хочу прокрутить каждый элемент списка, переданного в функцию. Если это конструктор Y, то я хочу вызвать некоторую функцию на нем. Если это конструктор Z, я хочу пропустить его.

Если есть способ проверить это в операторе if, то это похоже на то, что нужно сделать, так как мне не нужно писать else. Тем не менее, я знаю только, как это проверить в матче.

Например:

let myFunct list = 
List.iter (fun x -> match x with
           | Y y -> otherFunction y
          ) list;;

Теперь, это дает мне предупреждение о том, что я не могу справиться с Z. Так что я могу добавить туда что-то вроде ...

let myFunct list = 
List.iter (fun x -> match x with
           | Y y -> otherFunction y
           | Z z -> (*skip*)
          ) list;;

Конечно, я не могу просто оставить матч Z пустым ...

Как мне добиться того, что я пытаюсь сделать?

Ответы [ 3 ]

6 голосов
/ 30 сентября 2011

Просто верните единицу (т. Е. ()) в случае Z.

Вы уверены, что хотите List.iter. Он в основном используется для применения функции для побочного эффекта.

Более идиоматический подход в функциональных программах - отфильтровать список с помощью List.filter, а затем применить преобразование ко всем оставшимся элементам, используя List.map.

1 голос
/ 30 сентября 2011

Lambdageek ответ для List.iter правильный. Вам просто нужно использовать () в качестве результата в любом случае, когда вам нечего делать. Все различные случаи вашего match выражения должны возвращаться (), когда вы выполняете итерацию. Вот что такое List.iter.

Все остальные (на мой взгляд, справедливо) обеспокоены тем, что вы, возможно, не захотите использовать List.iter. Это может быть первое, о чем вы думаете, когда пришли из других (императивных) языков, но итерация per se вовсе не так часто используется при функциональном программировании. Если вы изучаете OCaml по какому-либо курсу, даже менее вероятно, что вы захотите использовать List.iter. Курс по OCaml определенно начнется с изучения функциональных частей. Чтобы мыслить функционально, вы хотите думать о преобразовании значений из одной формы в другую (то есть, применяя к ним функции).

Допустим, вы хотели использовать List.filter. Затем, как вы говорите, вы в конечном итоге сделаете выражение match, но вместо возврата () во всех различных случаях вы захотите вернуть логическое значение (true или false) в каждом случае. Если вы вернете true, значение будет включено в итоговый список. Если вы вернете false, значение не будет включено в итоговый список. Еще раз, это то, что List.filter это все. Вот некоторый код, который возвращает новый список, содержащий только элементы данного списка, которые имеют конструктор Z.

let myFunc list =
    List.filter
        (fun x -> match x with Z _ -> true | _ -> false)
        list

Я не уверен, что это помогает, но я думаю, что я пытаюсь сказать, что использование match не сложно. Вам просто нужно охватить каждый случай. Это хорошо, вы хотите, чтобы ваш код работал во всех случаях!

1 голос
/ 30 сентября 2011

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

См. Документы здесь для получения дополнительной информации о методах в модуле списка.http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html

В данный момент у меня нет доступа к компилятору OCaml, но код будет выглядеть примерно так:

List.iter (fun x -> ....) (List.filter (fun x -> ...) mylist)

...