From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by c5ff346549e7 (Postfix) with ESMTPS id BB8E45D5 for ; Tue, 26 Nov 2019 08:33:43 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.69,245,1571695200"; d="asc'?scan'208,217";a="413501126" Received: from sympa.inria.fr ([193.51.193.213]) by mail2-relais-roc.national.inria.fr with ESMTP; 26 Nov 2019 09:33:42 +0100 Received: by sympa.inria.fr (Postfix, from userid 20132) id 5F5887ED21; Tue, 26 Nov 2019 09:33:42 +0100 (CET) Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id 6230A7ED20 for ; Tue, 26 Nov 2019 09:33:39 +0100 (CET) X-IronPort-AV: E=Sophos;i="5.69,245,1571695200"; d="asc'?scan'208,217";a="413501118" Received: from set.irisa.fr (HELO set) ([131.254.10.170]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/AES256-GCM-SHA384; 26 Nov 2019 09:33:38 +0100 User-agent: mu4e 1.2.0; emacs 26.3 From: Alan Schmitt To: "lwn" , "cwn" , caml-list@inria.fr Date: Tue, 26 Nov 2019 09:33:35 +0100 Message-ID: <87tv6rjau8.fsf@inria.fr> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="===-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" Subject: [Caml-list] Attn: Development Editor, Latest OCaml Weekly News Reply-To: Alan Schmitt X-Loop: caml-list@inria.fr X-Sequence: 17882 Errors-to: caml-list-owner@inria.fr Precedence: list Precedence: bulk Sender: caml-list-request@inria.fr X-no-archive: yes List-Id: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --===-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: multipart/alternative; boundary="==-=-=" --==-=-= Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Hello Here is the latest OCaml Weekly News, for the week of November 19=20 to 26, 2019. Table of Contents =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80 tiny_httpd 0.1 printbox.0.3 v0.13 release of Jane Street packages opam2nix (v1) GitHub Actions for OCaml / opam now available OCurrent 0.1 (CI/CD pipeline eDSL) New pages for OCaml API Irmin 2.0.0 release Tail cascade: a new indentation style for some OCaml constructs Old CWN tiny_httpd 0.1 =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90 Archive: Simon Cruanes announced =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 Hello and good morning, I'm pleased to announce that=20 [tiny_httpd] 0.1 has been released and is on opam. The goal is to emulate python's standard `http.server' by=20 providing a 0-dependencies, minimalist, simple HTTP server for embedding in applications that are not primarily a website, with very basic=20 routing (thanks to `Scanf'). A binary `http_of_dir' is also distributed=20 and can be used to serve a directory, with optional upload of files. [tiny_httpd] printbox.0.3 =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90 Archive: Simon Cruanes announced =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80 =E2=94=82 let b =3D =E2=94=82 let open PrintBox in =E2=94=82 PrintBox_unicode.setup(); =E2=94=82 frame @@ grid_l [ =E2=94=82 [text "subject"; text_with_style Style.bold "announce:=20 printbox 0.3"]; =E2=94=82 [text "explanation"; =E2=94=82 frame @@ text {|PrintBox is a library for rendering nested= =20 tables, =E2=94=82 trees, and similar structures in monospace text or=20 HTML.|}]; =E2=94=82 [text "github"; =E2=94=82 text_with_style Style.(bg_color Blue)=20 "https://github.com/c-cube/printbox/releases/tag/0.3"]; =E2=94=82 [text "contributors"; =E2=94=82 vlist_map (text_with_style Style.(fg_color Green))=20 ["Simon"; "Guillaume"; "Matt"]]; =E2=94=82 [text "dependencies"; =E2=94=82 tree empty =E2=94=82 [tree (text "mandatory") =E2=94=82 [text "dune"; text "bytes"]; =E2=94=82 tree (text "optional") =E2=94=82 [text "uutf"; text "uucp"; text "tyxml"]]]; =E2=94=82 [text "expected reaction"; text "=F0=9F=8E=89"]; =E2=94=82 ] =E2=94=82 =E2=94=82 let () =3D print_endline @@ PrintBox_text.to_string b =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80 ([actual link to the release]) [actual link to the release] v0.13 release of Jane Street packages =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90= =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90 Archive: Xavier Clerc announced =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 We are pleased to announce the v0.13 release of Jane Street=20 packages! This release comes with 14 new packages, and a number of fixes=20 and enhancements. The documentation for this release is available on=20 our website: The remainder of this mail highlights the main changes since the=20 v0.12 release; we hope it will be useful to developers in the process=20 of migrating to the new version. A comprehensive changelog is=20 available at the end. Notable changes =E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2= =95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C =E2=80=A2 Changed `Base', `Core_kernel', and `Core' functions to raise `Not_found_s' instead of `Not_found'. `Hashtbl.find_exn' and `Map.find_exn' now include the key in their error message. =E2=80=A2 Changed `Core' and `Core_kernel' to export `int' comparison=20 rather than polymorphic comparison. =E2=80=A2 Removed the "robust" float comparison operators (`>.', `=3D.',= =20 =E2=80=A6) from the default namespace. =E2=80=A2 Replaced `sexp_*' types (`sexp_list', `sexp_option',=20 `sexp_opaque', =E2=80=A6) with preprocessor attributes (`[@sexp.list]',=20 `[@sexp.option]', `[@sexp.opaque]', =E2=80=A6). =E2=80=A2 Changed `let%map' syntax from `let%map.Foo.Let_syntax' to `let%map.Foo'. =E2=80=A2 Added to `match%optional' support for specifying a path, so=20 you can write `match%optional.Foo foo_option' rather than `let open Foo.Optional_syntax in match%optional foo_option'. =E2=80=A2 Improved `Base.Backtrace' so that it enables recording of=20 backtraces in more situations, specifically when `OCAMLRUNPARAM' is=20 defined but doesn't mention the backtrace flag, `b'. =E2=80=A2 Added javascript support for `Zarith', `Bigint', `Bignum', and `Bigdecimal'. =E2=80=A2 Changed `Hashtbl.create''s default `size' from 128 to 0. =E2=80=A2 Changed `Core_kernel.Command' so that all commands accept=20 double dash flags: `--help', `--version', and `--build-info'. New packages =E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2= =95=8C=E2=95=8C=E2=95=8C=E2=95=8C =E2=80=A2 async_udp (): UDP=20 support for Async. =E2=80=A2 async_websocket=20 (): A library that implements the websocket protocol on top of=20 Async. =E2=80=A2 bonsai (): A library for building dynamic webapps, using Js_of_ocaml. =E2=80=A2 postgres_async=20 (): OCaml/async implementation of the postgres protocol (i.e.,=20 does not use C-bindings to libpq). =E2=80=A2 ppx_cold (): Expands `[@cold]' into `[@inline never][@specialise never][@local=20 never]'. =E2=80=A2 ppx_pattern_bind=20 (): A ppx for writing fast incremental bind nodes in a pattern=20 match. =E2=80=A2 ppx_python (): `[@@deriving]' plugin to generate Python conversion functions. =E2=80=A2 ppx_yojson_conv=20 (): `[@@deriving]' plugin to generate Yojson conversion functions. =E2=80=A2 ppx_yojson_conv_lib (): Runtime=20 lib for `ppx_yojson_conv'. =E2=80=A2 pythonlib (): A=20 library to help writing wrappers around OCaml code for python. =E2=80=A2 sexp_select (): A=20 library to use CSS-style selectors to traverse sexp trees. =E2=80=A2 timezone (): Time-zone handling. =E2=80=A2 toplevel_backend=20 (): Shared backend for setting up toplevels. =E2=80=A2 zarith_stubs_js=20 (): Javascript stubs for the Zarith library. Deprecations / Removals =E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2= =95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95= =8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C `Async_kernel': =E2=80=A2 Deprecated monadic `ignore' functions in favor of `ignore_m'. `Base': =E2=80=A2 Deleted `Array.replace' and `replace_all' functions, which=20 have been deprecated since before the last public release. =E2=80=A2 Deprecated `Result.ok_unit'; use `Ok ()'. =E2=80=A2 Removed the `Monad' and `Applicative' interfaces' `all_ignore' function; it was previously deprecated and replaced by=20 `all_unit'. =E2=80=A2 Removed `List.dedup', which has been deprecated since 2017-04. =E2=80=A2 Removed `String' mutation functions, which have been=20 deprecated in favor of `Bytes' since 2017-10. =E2=80=A2 Deprecated `Array.truncate', `Obj_array.unsafe_truncate', and `Uniform_array.unsafe_truncate'. =E2=80=A2 Deprecated `Sys.argv', which has been superseded by=20 `get_argv', which is a function, reflecting the fact that `argv' can=20 change (as of OCaml 4.09). `Core_kernel': =E2=80=A2 Removed `Core_kernel.Std', which had been deprecated for a=20 year. =E2=80=A2 Deprecated type `Command.Spec.param' in favor of=20 `Command.Param.t'. =E2=80=A2 Removed `Hashtbl' functions that had been deprecated for=20 years. =E2=80=A2 Removed `Float.to_string_round_trippable', which has been=20 deprecated in favor of `to_string' since 2017-04. =E2=80=A2 Deprecated `Fqueue' functions where one should use `Fdeque'=20 instead: `bot', `bot_exn', and `enqueue_top'. =E2=80=A2 Deleted `Bus.unsubscribes', which will be obviated by a=20 performance improvement to `Bus.unsubscribe'. `Timing_wheel': =E2=80=A2 Removed the `alarm_upper_bound' function, which has been=20 deprecated for 6 months, and superseded by `max_allowed_alarm_time'. Moves =E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C `Core_kernel': =E2=80=A2 Moved `Bounded_int_table' to a standalone library. =E2=80=A2 Moved the `Pool' and `Tuple_type' modules to a standalone=20 library, `Tuple_pool'. `Async_unix': =E2=80=A2 Moved `Unix.Fd.replace' into a `Private' submodule. Changelog =E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2= =95=8C Please visit opam2nix (v1) =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90 Archive: Tim Cuthbertson announced =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 Anouncing opam2nix (v1) [opam2nix] generates [nix] expressions from the [opam] OCaml=20 package repository. It works similarly to [bundix], [node2nix], etc: You run an (impure) command to resolve all transitive dependency versions using the current opam repository, generating a .nix=20 file that locks down the exact package sources and versions. Then=20 this file can be imported to provide `buildInputs' for building your ocaml project in nix. *What is nix and why would I care?* Well, that's a long story=20 but the headline benefits of nix are: =E2=80=A2 reproducible builds (if it builds for me, it builds for you) =E2=80=A2 stateless (you don't set up switches and then install=20 packages, each expression specifies everything it needs, and anything you=20 don't have is fetched/built on demand) =E2=80=A2 language agnostic (takes care of non-ocaml dependencies) It's sadly not a shallow learning curve, but those benefits are=20 hard to find elsewhere, so I obviously think it's worthwhile. So if=20 you use nix (or would like to), please give it a try and provide feedback. I'll (slowly) start working on upstreaming it into=20 nixpkgs. [opam2nix] [nix] [opam] [bundix] [node2nix] GitHub Actions for OCaml / opam now available =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90= =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90 Archive: Anil Madhavapeddy announced =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80 I was in the [GitHub Actions] beta program and forward ported my=20 code to the latest version that just went public. It's a pretty=20 simple way to get your OCaml code tested on Linux, macOS and Windows,=20 without requiring an external CI service. The action attempts to=20 provide a homogenous interface across all three operating systems, so=20 invoking 'opam' from subsequent actions should "just work". You can find it here: =E2=80=A2 In the GitHub Marketplace at =E2=80=A2 Source code on =E2=80=A2 Hello World usage on =E2=80=A2 Usage in ocaml-yaml: =E2=80=A2=20 =E2=80=A2 An [example ocaml-yaml run] This should be considered fairly experimental as GH Actions is=20 so new. If you do use it, then consider [updating this issue with your=20 usage]. It does not current supporting caching yet, but is pretty fast=20 to bootstrap (~4minutes). It also doesn't have any higher level purpose other than to set=20 up an opam environment, since most of the additional functionality=20 such as revdeps testing is planned for addition to the [ocurrent DSL]. Nevertheless, this GH feature will hopefully be useful for=20 smaller projects without a lot of computational requirements. Let me=20 know how it goes! Windows is currently supported through @fdopen's excellent fork=20 that uses Cygwin. As Windows support is being mainlined into opam=20 itself at the moment, I'm hoping that we will gradually move over to=20 that. That should eventually remove the need for two separate opam-repositories, so I won't be adding any features that are=20 Linux or macOS-specific and do not work on the Cygwin version. [GitHub Actions] [example ocaml-yaml run] [updating this issue with your usage] [ocurrent DSL] OCurrent 0.1 (CI/CD pipeline eDSL) =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90= =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90 Archive: Thomas Leonard announced =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 [OCurrent] 0.1 has just been released to opam-repository. OCurrent is an OCaml eDSL intended for writing build/test/deploy pipelines. It is being used as the engine for [ocaml-ci] and the [docker-base-images] builder (used to build the OCaml Docker=20 images, such as `ocurrent/opam:alpine-3.10-ocaml-4.08'). Other good uses=20 might be building and redeploying a Docker service or a unikernel=20 whenever its source repository changes. It can be run locally as a single=20 Unix process. An OCurrent pipeline is written as an OCaml program, but the=20 OCurrent engine ensures that it is kept up-to-date by re-running stages=20 when their inputs change. A web UI is available so you can view your pipeline and see its current state. OCurrent can statically analyse the pipelines before they have=20 run, allowing it to run steps in parallel automatically and to=20 display the whole pipeline. It does this using a light-weight alternative to arrows, which doesn't require programming in an awkward=20 point-free style. See [CI/CD Pipelines: Monad, Arrow or Dart?] for more=20 about that. The basic functionality can be extended using "plugins" (just=20 normal OCaml libraries). Plugins are available for interacting with=20 Docker, Git, GitHub and Slack. These are in separate packages (e.g. `current_github') to avoid having the base package pull in=20 too many dependencies). There is also an optional Cap'n Proto RPC interface, in the `current_rpc' opam package. This is used, for example, by=20 [citty] to provide a TTY interface to ocaml-ci. [The OCurrent wiki] contains examples, and documentation on the various plugins. Here's an example pipeline (from the base image builder): [OCurrent] [ocaml-ci] [docker-base-images]=20 [CI/CD Pipelines: Monad, Arrow or Dart?] [citty] [The OCurrent wiki] Anil Madhavapeddy then added =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80 For those curious about the relation to the existing CI used in opam-repository, then it is no coincidence that @talex5 is the=20 author of both :-) This DSL is the next iteration of the [datakit-ci], but=20 specialised to be faster and simpler for extending with OCaml and more complex workflows that our OCaml Platform tools need these days (like ocamlformat linting, or dune expect promotion, or odoc cross-referenced doc generation). We are planning a smooth=20 migration next year over to the new system, but wanted to release this=20 early to show you some of the pieces going into this new iteration. I am particularly excited about the new tty-based interface that=20 saves an awful lot of clicking around on web UIs for CI results=E2=80=A6 [datakit-ci] New pages for OCaml API =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90 Archive:=20 Continuing this thread, sanette announced =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80 I have uploaded a new version (same link ) =E2=80=A2 background color for links in the TOC @Maelan =E2=80=A2 more indentation for value descriptions @Maelan, @grayswandyr =E2=80=A2 word wrapping long `
' codes @grayswandyr
  =E2=80=A2 type table: remove `(*' and `*)', give more space to code wrt
    comments, diminish comment's color @grayswandyr

  searching is not ready yet=E2=80=A6 please wait suggestions for dark=20
  theme
  welcome


sanette later added
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80

  I have just uploaded a new version with a basic search engine.
  =E2=80=A2 for each page, you can search values/modules
  =E2=80=A2 in the general index page, the search includes also the=20
  descriptions
  =E2=80=A2 search results are ranked by relevance

  the downside is that each page now comes with an index of about=20
  570Kb
  in the form of an index.js file. I'm kind of hoping that the=20
  browser
  will cache this, but I'm not sure. It would be maybe better to=20
  only
  load the index file on demand.


Irmin 2.0.0 release
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90

  Archive:=20
  


Thomas Gazagnaire announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80

  On behalf of the Irmin development team, I am very happy to=20
  announce
  the release of Irmin 2.0.0, a major release of the Git-like
  distributed branching and storage substrate that underpins
  [MirageOS]. We began the release process for all the components=20
  that
  make up Irmin [back in May 2019], and there have been close to=20
  1000
  commits since Irmin 1.4.0 released back in June 2018. To=20
  celebrate
  this milestone, we have a new logo and opened a dedicated=20
  website:
  [irmin.org].

  More details here:=20
  


[MirageOS] 

[back in May 2019]


[irmin.org] 


Tail cascade: a new indentation style for some OCaml constructs
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=
=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=
=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90

  Archive:
  


gasche announced
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  I recently decided to change my indentation style for certain=20
  OCaml
  constructs in a way that I'm going to describe below. I just=20
  coined a
  name for this approach, "tail cascade". I'm creating this topic=20
  to
  convince everyone that this is a cool idea you should adopt as
  well. Or at least tolerate it when you review other people's=20
  code.


Problem
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C

  Programs that heavily use `match' often see a shift to the right=20
  due
  to nested indentation.

  =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
  =E2=94=82 match foo with
  =E2=94=82 | Foo -> ...
  =E2=94=82 | Bar x ->
  =E2=94=82   match bar x with
  =E2=94=82   | FooBar -> ...
  =E2=94=82   | Blah y ->
  =E2=94=82     match f y with
  =E2=94=82     | Some z ->
  =E2=94=82       ...
  =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  Another problem with this style is that it suffers from the=20
  "dangling
  bar" issue: if you try to add a new case for one of the exterior
  `match', it is parsed as belonging to the innermost `match'.=20
  People
  have been recommending (rightly) to use `begin match .. end' for=20
  all
  nested match constructs to avoid this issue.

  =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
  =E2=94=82 match foo with
  =E2=94=82 | Foo -> ...
  =E2=94=82 | Bar x ->
  =E2=94=82   begin match bar x with
  =E2=94=82   | FooBar -> ...
  =E2=94=82   | Blah y ->
  =E2=94=82     begin match f y with
  =E2=94=82     | None -> ...
  =E2=94=82     | Some z ->
  =E2=94=82       ...
  =E2=94=82     end
  =E2=94=82   (* now this is safe *)
  =E2=94=82   | FooBlah -> ...
  =E2=94=82   end
  =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  But still the unpleasant shift to the right remains.


Proposal: cascading tail case
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C

  We should in general use `begin match .. end' for nested=20
  matches. But
  the "cascading tail case" proposal is to *not* do it for the=20
  *last*
  case of the pattern-matching, and instead *de-indent* (dedent)=20
  this
  last case =E2=80=93 tail case.

  =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
  =E2=94=82 match foo with
  =E2=94=82 | Foo -> ...
  =E2=94=82 | Bar x ->
  =E2=94=82 match bar x with
  =E2=94=82 | FooBar -> ...
  =E2=94=82 | Blah y ->
  =E2=94=82 match f y with
  =E2=94=82 | None -> ...
  =E2=94=82 | Some z ->
  =E2=94=82 ...
  =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  Note that with this indentation style, the "dangling match"=20
  problem is
  also avoided: unlike with the original, non `end'-protected=20
  program,
  the indentation makes it immediately obvious that any further=20
  case
  will be attached to the innermost match, and not any of the=20
  exterior
  ones.

  A program using this "cascading tail" approach should always use
  `begin match .. end' for nested matches, except for a nested=20
  match
  returned within the last branch of an outer match, which can
  (optionally) be dedented instead.

  The choice to dedent the last case corresponds to encouraging a
  sequential reading of the program, where the other cases are
  "auxiliary cases" checked first and dispatched quickly, and the=20
  last
  case is the "main part" where the "rest" of the logic of the=20
  program
  lies. This pattern is typical of nested pattern-matching on the
  `option' or `result' type for example:

  =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
  =E2=94=82 match foo x with
  =E2=94=82 | Error err ->
  =E2=94=82   fail_foo_error err
  =E2=94=82 | Ok y ->
  =E2=94=82 match bar y with
  =E2=94=82 | Error err ->
  =E2=94=82   fail_bar_error err
  =E2=94=82 | Ok () ->
  =E2=94=82 ...
  =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  Remark: it is *not* always the case that the `Error' constructor=20
  is
  the auxiliary case, and the `Ok' constructor is the main case;
  sometimes we implement fallback logic like "if `foo' work then=20
  we are
  good, but otherwise we have to do this and that", and the error=20
  case
  is the most salient (and longer) part of the program logic. I=20
  would
  recommend being mindful, when you write code, of whether there=20
  is a
  most convincing way to "sequentialize" it (distinguish auxiliary=20
  and
  main/tail case), and avoid using cascading tails when there is=20
  no
  clear sequentialization choice.

  Remark: some cases of tail cascades can be linearized by using a=20
  good
  definition of "bind" and a monadic style. This tends to be very
  limited however: it fixes one of the constructors to always be=20
  the
  "tail" constructor (always `Some', always `Ok'), and it only=20
  works
  when the handling of the other constructors is very homogeneous
  (typically: return directly). In real code, many situations=20
  occur
  where the monadic style doesn't fit the problem, but tail=20
  cascade does
  help writing a readable program.


Generalization: tail cascade
=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=
=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=
=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=E2=95=8C=
=E2=95=8C=E2=95=8C=E2=95=8C

  While I have never seen cascading tail cases in real-world OCaml=20
  code
  before (I'm happy to be given pointers; I think that the idea is=20
  not
  new, but I'm not aware of previous attempts to give it a catchy=20
  name
  and spread the cascade love), this is in fact a new (to me)=20
  instance
  of a common technique that is used for other OCaml constructs:

  =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
  =E2=94=82 if foo x then ...
  =E2=94=82 else if bar x then ...
  =E2=94=82 else ... (* this `tail else` was dedented *)
  =E2=94=82
  =E2=94=82 let x =3D foo in
  =E2=94=82 let y =3D bar in (* this `tail let` was dedented *)
  =E2=94=82 ...            (* and the rest as well *)
  =E2=94=82
  =E2=94=82 bind foo @@ fun x ->
  =E2=94=82 bind bar @@ fun y -> (* this "tail function body" was dedented=
=20
  *)
  =E2=94=82 ...                  (* and the rest as well *)
  =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  I would call "tail cascade" (or maybe: "cascading tail") the=20
  idea of
  dedenting the "rest" of an OCaml expression (compared to a=20
  strict
  tree-nesting-based approach) when it morally describes the=20
  "rest" of
  the expression. I use the name "tail" because those expressions=20
  are
  almost always in tail-position in the sense of tail-calls.

  This general approach legitimizes some styles that I have seen,=20
  and
  sometimes used, in the wild, while at the same time considering=20
  that I
  may have been doing something improper, for example:

  =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
  =E2=94=82 if foo then blah else
  =E2=94=82 ... (* dedented *)
  =E2=94=82
  =E2=94=82
  =E2=94=82 Fun.protect
  =E2=94=82   ~finally:(...)
  =E2=94=82 @@ fun () ->
  =E2=94=82 ... (* dedented *)
  =E2=94=82
  =E2=94=82
  =E2=94=82 try simple_approach with exn ->
  =E2=94=82 ... (* dedented *)
  =E2=94=82
  =E2=94=82
  =E2=94=82 1 +
  =E2=94=82 2 + (* dedented *)
  =E2=94=82 ... (* dedented *)
  =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  Remark: after a `then' or `else', many people share the=20
  reasonable
  view that any expression containing imperative constructs (`foo;=20
  bar')
  should be enclosed in a `begin .. end' block to avoid
  surprising-precedence issue. Just as for nested `match', this
  recommendation should be lifted for "tail else" constructs.

  Remark: The last example is a case where the dedented=20
  expressions are
  *not* in tail-position from a runtime-evaluation point of view.=20
  I am
  not sure as whether the two notions should be made to coincide=20
  more
  strongly, but in any case I'm not fond of the style in this=20
  particular
  example, I prefer to move the infix operator to the beginning of=20
  the
  next line instead, following a different style and=20
  justification.

  The possibility this "cascading tail" style today crucially=20
  relies on
  the nesting properties of open-ended syntactic constructs,=20
  notably
  `let' (commonly cascaded), and now `match' and `if
  ... else'. Proposals to transition to a syntax where `match' and
  `else' are forced to take a closing marker are incompatible with=20
  the
  cascading style. I have not made my mind on whether this should=20
  be
  considered a blocker for those proposals, but at least it shows=20
  that
  having the open-ended form available has value for certain=20
  programs.


Louis Gesbert then said
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80

  @gasche I prototyped a dedicated option in `ocp-indent', if=20
  you're
  interested in trying it out :)
  =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80
  =E2=94=82 opam pin=20
  git+https://github.com/OCamlPro/ocp-indent#match-tail-cascade
  =E2=94=82 echo "match_tail_cascade=3Dtrue" >> ~/.ocp-indent
  =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80


Old CWN
=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90

  If you happen to miss a CWN, you can [send me a message] and=20
  I'll mail
  it to you, or go take a look at [the archive] or the [RSS feed=20
  of the
  archives].

  If you also wish to receive it every week by mail, you may=20
  subscribe
  [online].

  [Alan Schmitt]


[send me a message] 

[the archive] 

[RSS feed of the archives]=20


[online] 

[Alan Schmitt] 


--==-=-=
Content-Type: text/html
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable








OCaml Weekly News







OCaml Weekly News

Previous Week Up Next Week

Hello

Here is the latest OCaml Weekly News, for the week of November 19 to 26, 20= 19.

tiny_httpd 0.1

Simon Cruanes announced

Hello and good morning, I'm pleased to announce that tiny_httpd 0.1 has been released and is on o= pam.

The goal is to emulate python's standard http.server by provid= ing a 0-dependencies, minimalist, simple HTTP server for embedding in appli= cations that are not primarily a website, with very basic routing (thanks t= o Scanf). A binary http_of_dir is also distribute= d and can be used to serve a directory, with optional upload of files.

printbox.0.3

Simon Cruanes announced

3D"8e7c55c5ab69=

let b =3D
  let open PrintBox in
  PrintBox_unicode.setup();
  frame @@ grid_l [
    [text "subject"; text_with_style=
 Style.bold "announce: printbox 0.3"];
    [text "explanation";
    frame @@ text {|PrintBox is a library for rendering nested tables,
    trees, and similar structures in monosp=
ace text or HTML.|}];
    [text "github";
    text_with_style Style.(bg_color =
Blue) "https://github.com/c-cube/printbox/releases/t=
ag/0.3"];
    [text "contributors";
     vlist_map (text_with_style Style.(fg_color Gree=
n)) ["Simon"; "Guillaume"; "Matt"=
]];
    [text "dependencies";
    tree empty
      [tree (text "mandatory")
         [text "dune"; text "bytes"];
       tree (text "optional")
         [text "uutf"; text "uucp"; text "tyxml"]]];
    [text "expected reaction"; text =
"🎉"];
  ]

let () =3D print_=
endline @@ PrintBox_text.to_string b

(actual lin= k to the release)

v0.13 release of Jane Street packages

Xavier Clerc announced

We are pleased to announce the v0.13 release of Jane Street packages!

This release comes with 14 new packages, and a number of fixes and enhancements. The documentation for this release is available on our website:

https://ocam= l.janestreet.com/ocaml-core/v0.13/doc/

The remainder of this mail highlights the main changes since the v0.12 release; we hope it will be useful to developers in the process of migrating to the new version. A comprehensive changelog is available at the end.

Notable changes

  • Changed Base, Core_kernel, and Core functions to raise Not_found_s instead of Not_found. Hashtbl.= find_exn and Map.find_exn now include the key in their error message.
  • Changed Core and Core_kernel to export = int comparison rather than polymorphic comparison.
  • Removed the "robust" float comparison operators (>., =3D., …) from the default namespace.
  • Replaced sexp_* types (sexp_list, sexp_= option, sexp_opaque, …) with preprocessor attributes ([@sexp.list], [@= sexp.option], [@sexp.opaque], …).
  • Changed let%map syntax from let%map.Foo.Let_syntax to let%map.Foo.
  • Added to match%optional support for specifying a path, so = you can write match%optional.Foo foo_option rather than let open Foo.Optional_syntax in match%optional foo_option.
  • Improved Base.Backtrace so that it enables recording of ba= cktraces in more situations, specifically when OCAMLRUNPARAM is defined= but doesn't mention the backtrace flag, b.
  • Added javascript support for Zarith, Bigint, = Bignum, and Bigdecimal.
  • Changed Hashtbl.create's default size from 12= 8 to 0.
  • Changed Core_kernel.Command so that all commands accept do= uble dash flags: --help, --version, and --build-= info.

New packages

Deprecations / Removals

Async_kernel:

  • Deprecated monadic ignore functions in favor of igno= re_m.

Base:

  • Deleted Array.replace and replace_all functio= ns, which have been deprecated since before the last public release.
  • Deprecated Result.ok_unit; use Ok ().
  • Removed the Monad and Applicative interfaces'= all_ignore function; it was previously deprecated and replaced by all_unit.
  • Removed List.dedup, which has been deprecated since 2017-0= 4.
  • Removed String mutation functions, which have been depreca= ted in favor of Bytes since 2017-10.
  • Deprecated Array.truncate, Obj_array.unsafe_truncate= , and Uniform_array.unsafe_truncate.
  • Deprecated Sys.argv, which has been superseded by ge= t_argv, which is a function, reflecting the fact that argv can change = (as of OCaml 4.09).

Core_kernel:

  • Removed Core_kernel.Std, which had been deprecated for a y= ear.
  • Deprecated type Command.Spec.param in favor of Comma= nd.Param.t.
  • Removed Hashtbl functions that had been deprecated for yea= rs.
  • Removed Float.to_string_round_trippable, which has been de= precated in favor of to_string since 2017-04.
  • Deprecated Fqueue functions where one should use Fde= que instead: bot, bot_exn, and enqueue_top.
  • Deleted Bus.unsubscribes, which will be obviated by a perf= ormance improvement to Bus.unsubscribe.

Timing_wheel:

  • Removed the alarm_upper_bound function, which has been dep= recated for 6 months, and superseded by max_allowed_alarm_time.

Moves

Core_kernel:

  • Moved Bounded_int_table to a standalone library.
  • Moved the Pool and Tuple_type modules to a st= andalone library, Tuple_pool.

Async_unix:

  • Moved Unix.Fd.replace into a Private submodul= e.

opam2nix (v1)

Tim Cuthbertson announced

Anouncing opam2nix (v1)

opam2nix generates <= a href=3D"https://nixos.org/">nix expressions from the opam OCaml package repository. It works similarly t= o bundix, node2nix, etc:

You run an (impure) command to resolve all transitive dependency versions u= sing the current opam repository, generating a .nix file that locks down th= e exact package sources and versions. Then this file can be imported to pro= vide buildInputs for building your ocaml project in nix.

What is nix and why would I care? Well, that's a long story but the = headline benefits of nix are:

  • reproducible builds (if it builds for me, it builds for you)
  • stateless (you don't set up switches and then install packages, each ex= pression specifies everything it needs, and anything you don't have is fetc= hed/built on demand)
  • language agnostic (takes care of non-ocaml dependencies)

It's sadly not a shallow learning curve, but those benefits are hard to fin= d elsewhere, so I obviously think it's worthwhile. So if you use nix (or wo= uld like to), please give it a try and provide feedback. I'll (slowly) star= t working on upstreaming it into nixpkgs.

GitHub Actions for OCaml / opam now available

Anil Madhavapeddy announced

I was in the GitHub Actions beta= program and forward ported my code to the latest version that just went pu= blic. It's a pretty simple way to get your OCaml code tested on Linux, mac= OS and Windows, without requiring an external CI service. The action attem= pts to provide a homogenous interface across all three operating systems, s= o invoking 'opam' from subsequent actions should "just work".

You can find it here:

This should be considered fairly experimental as GH Actions is so new. If = you do use it, then consider updating this issue with your usage. It does not current su= pporting caching yet, but is pretty fast to bootstrap (~4minutes).

It also doesn't have any higher level purpose other than to set up an opam = environment, since most of the additional functionality such as revdeps tes= ting is planned for addition to the ocurrent DSL. Neverthele= ss, this GH feature will hopefully be useful for smaller projects without a= lot of computational requirements. Let me know how it goes!

Windows is currently supported through @fdopen's excellent fork that uses C= ygwin. As Windows support is being mainlined into opam itself at the mome= nt, I'm hoping that we will gradually move over to that. That should event= ually remove the need for two separate opam-repositories, so I won't be add= ing any features that are Linux or macOS-specific and do not work on the Cy= gwin version.

OCurrent 0.1 (CI/CD pipeline eDSL)

Thomas Leonard announced

OCurrent 0.1 has just = been released to opam-repository.

OCurrent is an OCaml eDSL intended for writing build/test/deploy pipelines.= It is being used as the engine for ocaml-ci and the docker-base-images builder (used to build the OCaml Doc= ker images, such as ocurrent/opam:alpine-3.10-ocaml-4.08). Oth= er good uses might be building and redeploying a Docker service or a uniker= nel whenever its source repository changes. It can be run locally as a sing= le Unix process.

An OCurrent pipeline is written as an OCaml program, but the OCurrent engin= e ensures that it is kept up-to-date by re-running stages when their inputs= change. A web UI is available so you can view your pipeline and see its cu= rrent state.

OCurrent can statically analyse the pipelines before they have run, allowin= g it to run steps in parallel automatically and to display the whole pipeli= ne. It does this using a light-weight alternative to arrows, which doesn't = require programming in an awkward point-free style. See CI/CD= Pipelines: Monad, Arrow or Dart? for more about that.

The basic functionality can be extended using "plugins" (just normal OCaml = libraries). Plugins are available for interacting with Docker, Git, GitHub = and Slack. These are in separate packages (e.g. current_github= ) to avoid having the base package pull in too many dependencies).

There is also an optional Cap'n Proto RPC interface, in the current_r= pc opam package. This is used, for example, by citty to provide a TTY interface to ocaml-ci.

The OCurrent wiki= contains examples, and documentation on the various plugins.

Here's an example pipeline (from the base image builder):

3D"docker-base-images-thumb.png"

Anil Madhavapeddy then added

For those curious about the relation to the existing CI used in opam-reposi= tory, then it is no coincidence that @talex5 is the author of both :-)

This DSL is the next iteration of the datakit-ci, but specialised to be faster and simpler for extendi= ng with OCaml and more complex workflows that our OCaml Platform tools need= these days (like ocamlformat linting, or dune expect promotion, or odoc cr= oss-referenced doc generation). We are planning a smooth migration next ye= ar over to the new system, but wanted to release this early to show you som= e of the pieces going into this new iteration. I am particularly excited a= bout the new tty-based interface that saves an awful lot of clicking around= on web UIs for CI results…

New pages for OCaml API

Continuing this thread, sanette announced

I have uploaded a new version (same link https://sanette.github.io/ocaml-api/)

  • background color for links in the TOC @Maelan
  • more indentation for value descriptions @Maelan, @grayswandyr
  • word wrapping long <pre> codes @grayswandyr
  • type table: remove (* and *), give more space= to code wrt comments, diminish comment's color @grayswandyr

searching is not ready yet… please wait suggestions for dark theme welcome

sanette later added

I have just uploaded a new version with a basic search engine.

  • for each page, you can search values/modules
  • in the general index page, the search includes also the descriptions
  • search results are ranked by relevance

the downside is that each page now comes with an index of about 570Kb in th= e form of an index.js file. I'm kind of hoping that the browser will cache = this, but I'm not sure. It would be maybe better to only load the index fil= e on demand.

Irmin 2.0.0 release

Thomas Gazagnaire announced

On behalf of the Irmin development team, I am very happy to announce the re= lease of Irmin 2.0.0, a major release of the Git-like distributed branching= and storage substrate that underpins Mirage= OS. We began the release process for all the components that make up Ir= min back in May 2019, and there have been close to 1000 commits since Irmi= n 1.4.0 released back in June 2018. To celebrate this milestone, we have a = new logo and opened a dedicated website: irm= in.org.

More details here: https://tarides.com/blog/2019-11-21-irmin-v2

Tail cascade: a new indentation style for some OCaml construct= s

gasche announced

I recently decided to change my indentation style for certain OCaml constru= cts in a way that I'm going to describe below. I just coined a name for thi= s approach, "tail cascade". I'm creating this topic to convince everyone th= at this is a cool idea you should adopt as well. Or at least tolerate it wh= en you review other people's code.

Problem

Programs that heavily use match often see a shift to the right= due to nested indentation.

match f=
oo with
| Foo -&g=
t; ...
| Bar x -=
>
  match bar x with
  | FooBar -> ...
  | Blah =
y ->
    match f y with
    | Some z ->
      ...

Another problem with this style is that it suffers from the "dangling bar" = issue: if you try to add a new case for one of the exterior match, it is parsed as belonging to the innermost match. People = have been recommending (rightly) to use begin match .. end for= all nested match constructs to avoid this issue.

match f=
oo with
| Foo -&g=
t; ...
| Bar x -=
>
  begin match bar x w=
ith
  | FooBar -> ...
  | Blah =
y ->
    begin match f y w=
ith
    | None -> ...
    | Some z ->
      ...
    end
  (* now this is safe *)
  | FooBlah -> ...
  end

But still the unpleasant shift to the right remains.

Proposal: cascading tail case

We should in general use begin match .. end for nested matches= . But the "cascading tail case" proposal is to not do it for the = last case of the pattern-matching, and instead de-indent (dedent= ) this last case – tail case.

match f=
oo with
| Foo -&g=
t; ...
| Bar x -=
>
match bar x with
| FooBar =
-> ...
| Blah y =
->
match f y with
| None -&=
gt; ...
| Some z =
->
...

Note that with this indentation style, the "dangling match" problem is also= avoided: unlike with the original, non end-protected program,= the indentation makes it immediately obvious that any further case will be= attached to the innermost match, and not any of the exterior ones.

A program using this "cascading tail" approach should always use begi= n match .. end for nested matches, except for a nested match returne= d within the last branch of an outer match, which can (optionally) be deden= ted instead.

The choice to dedent the last case corresponds to encouraging a sequential = reading of the program, where the other cases are "auxiliary cases" checked= first and dispatched quickly, and the last case is the "main part" where t= he "rest" of the logic of the program lies. This pattern is typical of nest= ed pattern-matching on the option or result type = for example:

match f=
oo x with
| Error e=
rr ->
  fail_foo_error err
| Ok y -&=
gt;
match bar y with
| Error e=
rr ->
  fail_bar_error err
| Ok () -=
>
...

Remark: it is not always the case that the Error constr= uctor is the auxiliary case, and the Ok constructor is the mai= n case; sometimes we implement fallback logic like "if foo wor= k then we are good, but otherwise we have to do this and that", and the err= or case is the most salient (and longer) part of the program logic. I would= recommend being mindful, when you write code, of whether there is a most c= onvincing way to "sequentialize" it (distinguish auxiliary and main/tail ca= se), and avoid using cascading tails when there is no clear sequentializati= on choice.

Remark: some cases of tail cascades can be linearized by using a good defin= ition of "bind" and a monadic style. This tends to be very limited however:= it fixes one of the constructors to always be the "tail" constructor (alwa= ys Some, always Ok), and it only works when the h= andling of the other constructors is very homogeneous (typically: return di= rectly). In real code, many situations occur where the monadic style doesn'= t fit the problem, but tail cascade does help writing a readable program.

Generalization: tail cascade

While I have never seen cascading tail cases in real-world OCaml code befor= e (I'm happy to be given pointers; I think that the idea is not new, but I'= m not aware of previous attempts to give it a catchy name and spread the ca= scade love), this is in fact a new (to me) instance of a common technique t= hat is used for other OCaml constructs:

if foo =
x then ...
else if bar x then ...
else ... (* this `tail else` was dedente=
d *)

let x =3D foo in
let y =3D bar in (* this `tail let` was dedented *)
...            (* and the rest as well *=
)

bind foo @@ fun x ->
bind bar @@ fun y -> (* this "tail=
 function body" was dedented *)
...                  (* and the rest as well *)

I would call "tail cascade" (or maybe: "cascading tail") the idea of dedent= ing the "rest" of an OCaml expression (compared to a strict tree-nesting-ba= sed approach) when it morally describes the "rest" of the expression. I use= the name "tail" because those expressions are almost always in tail-positi= on in the sense of tail-calls.

This general approach legitimizes some styles that I have seen, and sometim= es used, in the wild, while at the same time considering that I may have be= en doing something improper, for example:

if foo =
then blah else
... (* dedented *)


Fun.protect
  ~finally:(...)
@@ f=
un () ->
... (* dedented *)


try simple_approach with exn ->
... (* dedented *)


1 +
2 + (* dedented *)
... (* dedented *)

Remark: after a then or else, many people share t= he reasonable view that any expression containing imperative constructs (foo; bar) should be enclosed in a begin .. end bloc= k to avoid surprising-precedence issue. Just as for nested match, this recommendation should be lifted for "tail else" constructs.

Remark: The last example is a case where the dedented expressions are no= t in tail-position from a runtime-evaluation point of view. I am not su= re as whether the two notions should be made to coincide more strongly, but= in any case I'm not fond of the style in this particular example, I prefer= to move the infix operator to the beginning of the next line instead, foll= owing a different style and justification.

The possibility this "cascading tail" style today crucially relies on the n= esting properties of open-ended syntactic constructs, notably let (commonly cascaded), and now match and if ... else. Proposals to transition to a syntax where match and else are forced to take a closing marker are incompatible with th= e cascading style. I have not made my mind on whether this should be consid= ered a blocker for those proposals, but at least it shows that having the o= pen-ended form available has value for certain programs.

Louis Gesbert then said

@gasche I prototyped a dedicated option in ocp-indent, if you'= re interested in trying it out :)

opam pin git+https://github.com/OCamlPro/ocp-i=
ndent#match-tail-cascade
echo "match_tail_cascade=3Dtrue" >> ~/.ocp-indent

Old CWN

If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a loo= k at the archive or the RSS feed of the archives<= /a>.

If you also wish to receive it every week by mail, you may subscribe online.

--==-=-=-- --=-=-=-- --===-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQEzBAEBCAAdFiEE6lXof/BsSVW56ZmGBA0KO07S5ccFAl3c42EACgkQBA0KO07S 5cfB9gf/czKc6TFbofxgE9nIYYCFKHj/ugAahe9Tj3tz9r4XsjOui8PmVJVkR1Pz vePH8oPCB72YPB8kUUYmCSdfy/g+VgujiDa1FDbJcMo+lFcDFtouEZsIS/FI31hR 4LehomvbjLb/x6Yd10DUarCptHoHnBXssg3FKkeP08GJHiO+qPoQTu/QEy4nASET DYy5zYhZ+XEheArpV52gFr2yUFEMXRhbLNVp+g4retI9WAwsBH5loHnNoQeOXAyq 3I4sYxQH2IxPHoM1k1NjDD2B0Ktj4T3fslfbSrhDDqOEscQOlorAFO0z522bMmB4 XW8SKn5MLDQEM4lWh+NCzIJA5DnOXw== =Xjob -----END PGP SIGNATURE----- --===-=-=--