Как выйти из итерации в OCaml? - PullRequest
3 голосов
/ 19 июля 2011

Я пытаюсь просмотреть список xl на List.fold_left, я хотел бы выйти из итерации, когда выполняется какое-то условие:

List.fold_left
  (fun x acc -> 
     if x = 5 then STOP THE ITERATION
     else x + acc)
xl

Может кто-нибудь сказать мне, как выразить STOP THE ITERATION здесь? Спасибо

Edit1: По приведенному выше коду я хотел бы сказать, что мы не прекращаем накопление, пока не встретим первое 5.

Ответы [ 3 ]

7 голосов
/ 19 июля 2011

Вы не можете сделать это со встроенными сгибами без исключения или если в оставшихся вызовах помечены некоторые неоперативные операции - как упоминается в phimuemue.В качестве альтернативы, вы можете просто написать очень простую хвостовую рекурсивную функцию, которая позаботится о раннем возврате,

(** Fold left on a list with function [f] until predicate [p] is satisfied **)
let rec fold_until f p acc = function
    | x :: xs when p x -> acc
    | x :: xs -> fold_until f p (f acc x) xs
    | [] -> acc

let accum_until_five =
    fold_until (fun acc x -> x + acc) (fun x -> x = 5) 0
3 голосов
/ 19 июля 2011

Следовательно, вам придется закодировать условие в аргумент x внутренней функции:

let t l =
    let (a,b) = 
        List.fold_left
            (fun ((accx, condition) as acc) x ->
                if condition then acc else (x+accx, x=5))
            (0,false) l
    in
    a;;

То есть вы должны сообщить своей функции, что - как только 5 будет замечено - она ​​должна просто возвращать то, что было сделано до сих пор.

0 голосов
/ 19 июля 2011

Есть несколько методов.

Либо вы добавляете флаг, который говорит ему прекратить суммирование, когда встречается 5, либо сначала фильтруете список, либо вы пишете свой собственный фолд.Все три из них очень просты в реализации.

Редактировать: опубликованный выше с дополнительным аргументом, вероятно, самый простой, ваш собственный фолд, вероятно, самый быстрый.

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

...