Lwt
Lwt — самая полярная библиотека для асинхронного программирования посредством промисов для не multicore OCaml. Под капотом использует libev.
Основное руководство находится на сайте Ocsigen. Помимо этого библиотека хорошо документирована в коде, как для просто юзеров, так и внутренние вещи.
Также активно используется в среде MirageOS.
Смотрите также
- CS3110, 8.7. Promises — детальной рассмотрение дизайна и устройства промисов;
- Скринкаст Промисы под капотом
- tiny-async-lib — игрушечная библиотека для понимания устройства Lwt, можете также посмотреть видео-разбор его исходного кода и пост с форума;
- Gist
dead_simple_read_files_in_lwt.ml
;
- Lwt: a Cooperative Thread Library — whitepaper про устройство Lwt;
- Детали реализации core'а смотрите в файле
lwt.ml
и т.д.;
Пример
Пример Lwt-программы, которая запрашивает первую страницу Google и терпит неудачу, если запрос не завершен в течение пяти секунд:
open Lwt.Syntax
let () =
let request =
let* addresses = Lwt_unix.getaddrinfo "google.com" "80" [] in
let google = Lwt_unix.((List.hd addresses).ai_addr) in
Lwt_io.(with_connection google (fun (incoming, outgoing) ->
let* () = write outgoing "GET / HTTP/1.1\r\n" in
let* () = write outgoing "Connection: close\r\n\r\n" in
let* response = read incoming in
Lwt.return (Some response)))
in
let timeout =
let* () = Lwt_unix.sleep 5. in
Lwt.return None
in
match Lwt_main.run (Lwt.pick [request; timeout]) with
| Some response -> print_string response
| None -> prerr_endline "Request timed out"; exit 1
(executable
...
(libraries lwt.unix))
Смотрите также
Ppx
ppx_lwt
— препроцессинг для удобной монадики с Lwt-промисами. Настоятельно рекомендуется к использованию!
let%lwt user = get_user_from_api "dad" in
(* ... *)
send_message "some text";%lwt
Switches
Смотрите также
- Рецепт по освобождения ресурсов
Библиотека Lwt предоставляет удобную абстракцию под названием switches (свитчи), эдакая область видимости, к которой мы привязываем ресурсы, и по выходу из которой они будут освобождены, даже в случае исключения.
Интерфейс модуля построен так, что он должен быть использован внутри функций с опциональными параметрами.
let connect ?switch uri =
let%lwt conn = open_connection uri in
(* ... *)
Lwt_switch.add_hock switch (fun () -> close_connection conn);
(* ... *)
let _ =
Lwt_switch.with_switch @@ fun switch ->
let%lwt conn_a = connect ~switch uri in
let%lwt conn_b = connect ~switch uri in
(* ... *)
Примеры использования
- Применение в библиотеке nats.ocaml
Never-промис
Тут мы создаем промис, который никогда не будет зарезолвен, а значит последовательность не продолжится.
let never = fst @@ Lwt.wait ()
let%lwt _ = never in (* ... *)