Asynchronous 如何组合Lwt过滤器?
我现在正在学习。我对使用异步进程用OCaml例程替换一些shell例程感兴趣 让我们看一看简化的第一次尝试,其中通过组合运行Asynchronous 如何组合Lwt过滤器?,asynchronous,ocaml,lwt,Asynchronous,Ocaml,Lwt,我现在正在学习。我对使用异步进程用OCaml例程替换一些shell例程感兴趣 让我们看一看简化的第一次尝试,其中通过组合运行cat的两个线程来创建过滤器: let filter_cat ()= Lwt_process.pmap_lines ("cat", [| "cat" |]) let filter_t () = Lwt_io.stdin |> Lwt_io.read_lines |> filter_cat () |> filter_cat () |
cat
的两个线程来创建过滤器:
let filter_cat ()=
Lwt_process.pmap_lines ("cat", [| "cat" |])
let filter_t () =
Lwt_io.stdin
|> Lwt_io.read_lines
|> filter_cat ()
|> filter_cat ()
|> Lwt_io.write_lines Lwt_io.stdout
let () =
filter_t ()
|> Lwt_main.run
这个过滤器以某种方式工作,但在其标准输入关闭而不是退出时挂起。如果我卸下其中一个过滤器\u cat
,它将按预期工作
我猜我没有适当地组合这些过滤器,因此无法连接我正在启动的两个线程。组成这些过滤器的正确方法是什么,以便程序在stdin
上读取EOF
后终止
您可以在中找到这个程序和Makefile。答案是Lwt中有一个小错误。有一个内部功能,用于执行管道:
(* Monitor the thread [sender] in the stream [st] so write errors are
reported. *)
let monitor sender st =
let sender = sender >|= fun () -> None in
let state = ref Init in
Lwt_stream.from
(fun () ->
match !state with
| Init ->
let getter = Lwt.apply Lwt_stream.get st in
let result _ =
match Lwt.state sender with
| Lwt.Sleep ->
(* The sender is still sleeping, behave as the
getter. *)
getter
| Lwt.Return _ ->
(* The sender terminated successfully, we are
done monitoring it. *)
state := Done;
getter
| Lwt.Fail _ ->
(* The sender failed, behave as the sender for
this element and save current getter. *)
state := Save getter;
sender
in
Lwt.try_bind (fun () -> Lwt.choose [sender; getter]) result result
| Save t ->
state := Done;
t
| Done ->
Lwt_stream.get st)
问题出在定义上
let getter = Lwt.apply Lwt_stream.get st
当
getter
进程遇到流的结尾时,它被保存,但是sender
丢失,这似乎阻止了完成。这可以通过改进getter
的定义来解决,方法是告诉它在到达流的末尾时充当发送者;对不起,我帮不上忙,也许可以试试ocsigen邮件列表。在风格方面,我发现filter\u cat
的定义非常混乱。写let filter_cat strm=…
然后|>filter_cat
会更清晰。而且,Lwt_main.run(filter_t())
会比filter_()|>Lwt_main.run
更清晰,因为Lwt_main.run
不是一个合理定义的过滤器。@martinbon Hi Martin,谢谢你的提示和提示!我会在邮件列表上询问。@MartinJambon,我打开了一个。