2015-04-07 2 views
0

Можно ли использовать Lwt.return как последний вызов в рекурсивной функции?Lwt и рекурсивные функции

У меня есть функция, которая компилируется отлично, но не работает должным образом и выглядит как функция f ниже. Предположим, что в этом примере нет проблемы с какой-либо функцией, представленной как g. Я просто пытаюсь выяснить, нормально ли иметь функцию со следующей формой или если лучше/проще (и Lwt-совместимый) способ:

let rec f (x : string list) (g : string -> unit Lwt.t) = 
    match List.length x with 
    | 0 -> Lwt.return() 
    | _ -> g (List.hd x) >>= fun() -> f (List.tl x) g 
;; 
val f : string list -> (string -> unit Lwt.t) -> unit Lwt.t = <fun> 

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

ответ

5

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

let rec f (xs : string list) (g : string -> unit Lwt.t) = 
    match xs with 
    | [] -> return() 
    | x :: xs -> g x >>= fun() -> f xs g 

Следующим шагом будет уведомление, что вы на самом деле просто выполнить итерацию больше список. Существует Lwt_list.iter_s для этого:

let f g xs = Lwt_list.iter_s g xs 

Это может упрощена еще более

let f = Lwt_list.iter_s 

Это означает, что вы даже не нужно писать такую ​​функцию, так как она уже есть.

И, наконец, не было проблем с рекурсией в вашей первоначальной реализации. Функция, которую вы предоставили, была рекурсивной.

2

Это зависит от того, возвращает ли g поток lwt, который уже вычислен, например return(), или запланирован и проснулся позже планировщиком lwt. В первом случае возможно, что вызов fun() -> f (List.tl x) g сделан сразу же, вместо того, чтобы планироваться позже, и это может увеличить стек в зависимости от того, какие оптимизации выполняются.

Я не думаю, что ваш код должен полагаться на такое сложное поведение. В этом конкретном примере, как показано в ответе @ ivg, вы должны использовать функции модуля Lwt_list.

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

+1

Я бы добавил, что, глядя на реализацию этого модуля, вероятно, хорошая идея, просто чтобы научиться справляться с ситуацией. –

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