# OCaml Weekly News

Hello

Here is the latest OCaml Weekly News, for the week of June 01 to 08, 2021.

## Boltzgen a test generator for teachers

### benoitbarbot announced

Boltzgen a test generator for teachers.

I am pleased to introduce https://git.lacl.fr/barbot/boltzgen; Boltzgen: Boltzmann sampler test generator is a tool to generate tests. Given a function signature it generates a random set of call of this function on generated random input. Inputs are generated using a Boltzmann sampler for unlabeled structure. This project has the following objectives:

• The primary goal was developing automatic grading system for purely functional programming exercises.
• Generate values with as little information as possible in most case only its type, the input by the user should be as small as possible;
• Strong probabilistic guarantee on the uniformity of the sample process thanks to Boltzmann sampler theory.

Given a function specification as a type signature :

```type 'a tree =   Empty  | Node of 'a tree * 'a * 'a tree
val sum: int list tree -> int
```

Boltzgen returns calls to this function :

```sum (Node((Empty,[],(Node((Empty,[(-4); (-2); 6],Empty))))))
sum (Node(((Node((Empty,[],Empty))),[13],Empty)))
sum (Node(((Node((Empty,[57],Empty))),[],(Node((Empty,[],(Node((Empty,[],(Node((Empty,[],Empty))))))))))))
...
```

You can try it with a buggy web interface here https://www.lacl.fr/~barbot/boltzgen/. Or install it with opam and test locally.

This tool was quickly developed during the first COVID 19 lockdown to quickly generate tests for programming exercise, many bugs remains, comments and contributions are welcome.

### Perry E. Metzger asked and benoitbarbot replied

Is there a reason that the utility of such a tool should be restricted to teachers? Property based randomized test systems also need tools like this for real world testing systems, do they not?

No, they should not be restricted to teachers, There are some tool in Haskell using the same technique for test generations. https://hackage.haskell.org/package/boltzmann-samplers

But this utility in particular was built with teaching and automatic grading in mind. When teaching the base of functional programming, most exercises are writing a well define standalone pure function.

When writing real world code, you often (depending on programming style) have a mutable custom type and function which interact with this type (ex HashTbl). Generating good test in this setting require additional work (but I have a few ideas).

For this tool additional developments are required to use it in a testing framework :

• The tool was written in hast, it probably should be entirely rewritten.
• Make it more reliable, right now I look at the generated result to make sure everything went right, more users are required !
• It should be integrated in a testing framework which requires, I think, moving the generation at compile time and not at the execution time, for each type several functions are generated, this generation should be done with ppx_deriving, I need help to do that.
• The ToDo list should be emptied, in particular I need help for the runtime generation of Ocaml value which requires knowledge in the internal Ocaml representation of value.

The theory of Boltzmann sampling is really beautiful in the fact that abstract math (namely formal power series) are used in practice to generate quite efficiently discrete value. I believe it could be used for efficient testing in general.

## Benchmark Tooling Engineer Position

### Celine announced

Tarides is looking for a Benchmark Tooling Engineer.

Tarides is a tech start-up founded in Paris in 2018 by pioneers of programming languages and cloud computing. Tarides develops a software infrastructure platform to deploy secure, distributed applications with strict resource constraints and low-latency performance requirements. Today, Tarides is composed of a diverse team of 35+ people.

We welcome applications from people of all backgrounds. We strive to create a representative, inclusive and friendly team, because we know that different experiences, perspectives and backgrounds make for a better workplace.

Please, don’t hesitate to contact me if you have any question, I’ll be more than happy to reply! :slight_smile:

## Lightweight OCaml Docker Images created by dune with Multi-Stage Builds

### Asya-kawai announced

I've written an article of Docker multi-stage Build for lightweight OCaml application using dune. I refered this article(https://discuss.ocaml.org/t/lightweight-ocaml-docker-images-with-multi-stage-builds/804) and customized to use dune.

### Yawar Amin then said

Nice write-up! You can also use opam lockfiles for reproducible builds: https://khady.info/opam-sandbox.html

The main difference in the Dockerfile will be:

```opam install . --deps-only --locked
```

You won't need to specify the packages in the install command, since they will be in the lockfile.

## Runtime Systems Engineer, OCaml Labs (UK) / Tarides (FR) / Segfault Systems (IN) / Remote

### KC Sivaramakrishnan announced

#### Multicore OCaml Runtime Systems Engineer

The Multicore OCaml team is hiring a runtime systems engineer to hack on the OCaml compiler. This position is being advertised jointly by OCaml Labs (UK), Tarides (France) and Segfault Systems (India).

##### Multicore OCaml

The Multicore OCaml project aims to bring native support for scalable concurrency and shared memory parallelism to the OCaml programming language. At its core, Multicore OCaml extends OCaml with effect handlers for expressing scalable concurrency, and a high-performance concurrent garbage collector aimed at responsive networked applications. Multicore OCaml is also the first industrial-strength language to be equipped with an efficient yet modular memory model, allowing high-level local program reasoning while retaining performance. Multicore OCaml is actively being developed and core features are being upstreamed to OCaml.

#### Qualifications & Experience

We are looking for an experienced (3Y+) systems engineer to join our team. Ideally, you will have:

• Excellent knowledge of C programming, parallel programming and Operating Systems.
• Worked on Compilers, Garbage Collectors and other runtime systems.
• Working knowledge of computer architecture and micro-architecture.
• Experience in analysing benchmarks and application performance.
• Track record of building production-quality software.
• Demonstrable open source contributions are a plus, but not required.
• Good communication skills in English; English is the corporate language.
• Experience of working in multidisciplinary teams.

#### Responsibilities

• Design and implement features in the Multicore OCaml runtime system.
• Develop tests and documentation for the Multicore OCaml features.
• Implement parallel benchmarks, analyse and improve the performance of Multicore OCaml programs.
• Submit pull requests to the OCaml programming language on GitHub, and work with the OCaml core team to get the features merged.
• Work with external clients and other teams to gather requirements, develop proposals, design solutions and communicate project statuses.
• Provide technical mentorship to other developers on the team.
• Communicate with the wider open-source community (discuss, blog posts, meetups, conferences, talks, etc.).

#### What we offer

• Competitive pay and benefits package.
• Flexible working hours and the possibility to work remotely within the UK / France / India.
• Supportive team environment with experienced Technical and Team Leads.
• The opportunity to grow with a fast-growing company.

#### Apply

• OCaml Labs (UK): Please send your CV and cover letter to jobs@ocamllabs.io.
• Tarides (France): Please send your CV and cover letter to apply@tarides.com.
• Segfault Systems (India): Please send your CV and cover letter to jobs@segfault.systems.

If shortlisted, you will have three online interviews starting with a general interview, followed by a technical interview, and finally an interview with the team.

We welcome applications from people of all backgrounds. We strive to create a representative, inclusive and friendly team because we know that different experiences, perspectives and backgrounds make for a better workplace.

## Timedesc 0.4.0 - date time handling library

### Darren announced

I'm pleased to announce the release of Timedesc 0.4.0.

Timedesc provides utilities to describe points of time, and properly handle calendar and time zone information.

Tutorial and API doc can be found here.

#### Features

• Timestamp and date time handling with platform independent time zone support
• Subset of the IANA time zone database is built into this library
• Supports Gregorian calendar date, ISO week date, and ISO ordinal date
• Supports nanosecond precision
• ISO8601 parsing and RFC3339 printing

#### Major changes since 0.1.0

• Added `ceil`, `floor`, and `round` to `Timedesc.Span`
• Better support for second fraction for non-RFC3339 pretty printers
• This includes automatic deduction of smallest number of fractional digits required for lossless representation, previously only used for RFC3339 pretty printers (see `{sec-frac:c}` description)
• Added `Timedesc.Zoneless` module for better time zone-less date time support
• Added `compare_chrono_min`, `compare_chrono_max`, and `compare_struct` for comparing `Timedesc.t` values

## serialization of closures

I just noticed that in 4.12+effect, in the road to multicore, we have now the nice exception:

```Failure("Serializing closures is broken in multicore")
```

This is a bit a pity: if you want to use both multicore and multi-machine parallelism, then, marshalling closures was useful for communication between machines in some cases. Is it a final decision or serialization of closures will be lost forever in OCaml ?

Remark: Closures is not marked as obsolete in Marshal.mli

### Xavier Leroy replied

I was not aware of this limitation of Multicore OCaml, and looking at its git history, it looks like it was introduced very early in the development, perhaps to make things simpler initially.

Marshalling of function closures has always been sort of experimental and not super reliable, but I was not expecting it to be incompatible with Multicore OCaml. We (the core dev team) will sort it out.

## OCaml compiler development newsletter, issue 2: May 2021

### gasche announced

I’m happy to publish the second issue of the “OCaml compiler development newsletter”. (This is by no means exhaustive: many people didn’t end up having the time to write something, and it’s fine.)

Feel free of course to comment or ask questions!

If you have been working on the OCaml compiler and want to say something, please feel free to post in this thread! If you would like me to get in touch next time I prepare a newsletter issue (some random point in the future), please let me know by email at (gabriel.scherer at gmail).

Previous issue:

#### Gabriel Scherer and Nicolas Chataing (@gasche and @nchataing)

[Gabriel writing] my main recent compiler-related activity is ongoing work with my intern Nicolas Chataing to implement a prototype of variant constructor unboxing, a core subset of what Jeremy Yallop proposed ( https://github.com/ocaml/RFCs/pull/14 ). Currently OCaml can "unbox" a variant if it has a single constructor (with a single parameter),

```type t = Int of int [@@unboxed]
```

Jeremy's idea is to support the case where there are other constructors, but the tag (immediate value or block constructor tag) of the constructor parameter is disjoint from the tag of any other value at this type.

```type t = Short of int [@unboxed] | Long of Mpz.t
```

Nicolas' prototype implementation is going along nicely, with some interesting challenges encountered and solved, and a few refactoring PRs along the way (#10307, #10412, #10428).

A key ingredient is to be able to compute the "head shape" of an OCaml type, an over-approximation of the set of possible tags of its values. We hit a few engineering and research issues in doing this. Where in the codebase should this be computed (beware of circular module dependencies)? Can we compute this information in a precise way in presence of mutually-recursive types, without risking non-termination?

We are taking inspiration from a general approach proposed by Leo White and Stephen Dolan to compute these kind of "type declaration properties" on-demand instead of as part of the type declaration's signature (see their proposal for "immediacy" at #10017, #10041 ), but our property is demanded more often (any occurrence of the constructor) and is more fine-grained (it is sensitive to type parameters), so we had to invent some solutions for new problems. (A close cousin is `get_unboxed_type_representation`, which avoids non-termination by using fuel, and we wanted something nicer than that.)

We discuss our handling of termination in (some) details in the following short abstract: Unfolding ML datatype definitions without loops.

#### Xavier Leroy (@xavierleroy)

I worked with Damien Doligez and Sadiq Jaffer on the "safe points" proposal (#10039), which is required to move forward with integrating Multicore OCaml. I re-expressed the static analyses that support the insertion of polls as backward dataflow analyses, making them simpler to understand and more robust. We also discussed whether to insert polls at the top of loops or at the bottom. Both strategies are implemented in the current state of the PR, and Sadiq is currently benchmarking them.

All this rekindled my interest in dataflow analyses. I wrote a generic backward dataflow analyzer, parameterized by an abstract domain and a transfer function (#10404). Originally I intended to use it only for the insertion of polls, but I also used it to reimplement the liveness analysis that plays a crucial role for register allocation and dead code elimination. A problem with the old liveness analysis is that it takes time exponential in the nesting of loops. The new generic analyzer avoids this pitfall by starting fixpoint iterations not systematically at the bottom of the abstract domain, but at the fixpoint found earlier, if any. This makes liveness analysis linear in the nesting of loops, and at worst cubic in the size of the function, instead of exponential.

Then I applied the same trick to the two passes that insert spills and reloads preventively (#10414). These are "analyze and simultaneously transform" passes, so I could not use the generic dataflow analyzer, but I could reuse the same improved fixpoint iteration strategy, again avoiding behaviors exponential in the nesting of loops. For instance, a trivial function consisting of 16 nested "for" loops now compiles in a few milliseconds, while it took several seconds before.

#### Jacques Garrigue (@garrigue)

No new PR this month, but I have kept working on those that were started in April, and are not yet merged:

• #10348 improves the way expansion is done during unification, to avoid some spurious GADT related ambiguity errors
• #10364 changes the typing of the body of the cases of pattern-matchings, allowing to warn in some non-principal situations; it also uncovered a number of principality related bugs inside the the type-checker
• #10337 enforces that one always manipulate a normalized view of types by making type_expr an abstract type (with Takafumi Saikawa (@t6s))

For this last PR, we have interestingly observed that while this multiplied the number of calls to repr by a factor of up to 4, resulting in a 4% overhead in stdlib for instance, we could see no performance degradation in the compilation of Coq.

I have also discovered a new principality bug in the implementation of GADTs (see #10348 again), which fortunately should not affect soundness.

In a slightly different direction, I have started working on a backend targetting Coq: https://github.com/COCTI/ocaml/tree/ocaml_in_coq

If you add the -coq option to ocamlc, you get a .v file in place of a .cmo. It is still in a very early stage, only able to compile core ML programs, including references. The main difference with coq-of-ocaml is that the translation is intended to be soundness preserving: the resulting Coq code can be typed and evaluated without axioms, and should reduce to the same resut as the source program, so that the type soudness of Coq underwrites that of ocaml (for individual programs). At this point, it only relies on a single relaxation of the positivity restriction of Coq.

#### Thomas Refis (@trefis)

Recently, Didier Rémy and I have been looking at modular explicits, a small extension between the core and module language to help manipulate first-class functors and give the illusion of abstraction over module arguments in the core language via a new construct (tentatively) called dependent functions.

This construct was first introduced in the context of the modular implicits proposal; roughly it's what you're left with if you take away the "resolution of implicit arguments" part of that proposal.

As such, it is a natural stepping stone towards modular implicits and already has its own self-contained PR: #9187, contributed by Matthew Ryan.

What Didier and I have been focusing on recently is producing a more formal description of the feature and its relationship to first-class modules, as well as some arguments to justify that it is reasonable and desirable to add it to the language, even in the absence of modular implicits.

#### Stephen Dolan (@stedolan)

I've just opened #10437, which allows explicit quantifiers for type variables in signatures and GADTs, a small feature I promised to OCaml maintainers a dozen of months ago. (The ulterior motive is that these explicit quantifiers give a good place to put layout information, but I think they're worth having on their own merits).

Note: The on-demand immediacy proposal in #10017 / #10041, which Gabriel mentioned above, is extracted from part of the kinding system in the experimental branch https://github.com/janestreet/ocaml/tree/layouts , which additionally allows quantification over types of a given immediacy / layout: for instance, one can write `type ('a : immediate) t = { foo : 'a }` and have inference, etc. work as expected.

The Safepoints PR #10039 has a few updates. It now has a new static analysis, written by Xavier Leroy and Damien Doligez, and has working code emitters on all 64-bit platforms.

The static analysis had some flexibility on poll placement in loops. We've benchmarked on amd64 and arm64, choosing to go with the option that results in slightly fewer instructions and branches across the Sandmark suite. Short of some refactoring I don't think there are any other oustanding issues with the PR.

Building on safepoints, I should soon have an attribute to propose which will enable users with atomic code blocks to safely migrate to a version of OCaml with safepoints. A draft PR or RFC will be coming very soon.

I am also doing some work on the instrumented runtime. One of the project's goals is to be able to continuously monitor OCaml applications running in a production environment. To that end I'm evaluating the instrumented runtime's performance overhead (both enabled and not), determining what work would be required to reduced the overhead and how we could modify the runtime to continuously extract metrics and events.

Ewan Mellor and I are working on a CI that'll make it easy to test individual changesets to the OCaml compiler and run "reverse dependencies" against a set of opam packages to isolate precisely what's causing a failure.

A failure to build an opam package can come from a variety of reasons. This can range from a build failure against a stable released compiler, to a failure on just OCaml trunk (but success on a released compiler), to a failure just on OCaml trunk + the PR in question. It's the triage of which of these situations is causing the package build failure that our new CI focusses on. Having this CI should let us quickly determine a PR's impact and potential regressions on the package ecosystem. Once the CI is stable on the OCaml multicore trees, I plan to submit it as a CI to run against mainline OCaml as well.

The working tree is at ocaml-multicore-ci (although it's called a "multicore CI", its really just turned into an "ocaml-compiler-ci" and we will rename the repository before a first release).

#### Florian Angeletti (@Octachron)

This week I have been working a bit on adding swaps and moves to the diffing based error messages for type declarations in #10361.

(And the release of the first alpha for OCaml 4.13.0)

The core idea of the PR is that when comparing

```type t = { a:int; b:int; c:int; d:int }
```

with

```type t = { a:int; c:int; d:int }
```

in an error message, it is better to notice that we are missing one field rather than trying to compare the fields `b` and `c`.

And with the machinery introduced for functor diffing, this is quite straigthforward to implement. I have been experimenting with this option since last december, and with the functor diffing PR merged #9331, I proposed a PR #10361 in April.

However, compared to functors, in type declarations, we have have one supplementary piece of information: the name of fields and constructors at a given position. Not using this piece of information yields slightly akward error messages:

```module M: sig type t = { a:int; b:int } end = struct type t = {b:int; a:int} end
```
```1. Fields have different names, a and b.
2. Fields have different names, b and a.
```

Here, it would be better to recognize that the two fields have been swapped.

One simple way to do this without increasing the diffing complexity is to identify swaps at posteriori on the optimal patch produced by the diffing algorithm.

In this way we can replace the previous error message by

```1<->2. Fields a and b have been swapped.
```

without increasing the cost of the error analysis.

A similar situation happens when the position of a field changes between the interface and the implementation

```module M: sig
type t = { a:unit; b:int; c:float}
end = struct
type t = { b:int; c:float; a:unit}
end
```

Explaining that the implementation can be transformed into the interface by adding a field `a` before the field `b` and deleting another field `a` after `c` is correct. But it is much nicer to sum up the issue as

```1->3. Field a has been moved from position 1 to 3
```

Both composite moves are now recognized.

People interested by error message in OCaml should also have a look at the great work by Antal Spector-Zabusky in #10407 to improve the module level error message by expanding them with a full error trace. (The two PRs are quite complementary.)

### Frédéric Recoules asked and gasche replied

Thank you @gasche and all the authors, these posts are really interesting!

I am looking forward to see all of this in the compiler, especially the work of @nchataing :upside_down_face:

Just reacting to the example, it would be nice if you can tag the type `Mpz.t` with `[@custom]` + `[@unboxed]` (is there a syntax to add multiple annotation?) because `custom` (hat, c.f. Unfolding ML datatype definitions without loops is distinguishable of `int` (hat and all other tag too).

One issue with `custom` tags is that they are currently only visible on the C side, the OCaml type is opaque, so the `[@custom]` annotation would have to be trusted by the compiler, which is meh. But the feature would be a special case of allowing shape restrictions on abstract types; which makes perfect sense.

### Rudi Grinberg asked and octachron replied

@octachron the progress in improving error messages is an exciting development. Thanks!

Is there any work to improve error messages for consumption by other tools? I know there's the json effort, but it seems to have been stalled. What about improving the compiler api to use the `sub` field for sub messages more consistently. This would greatly improve the presentation of errors to the user in lsp/merlin.

The json work for the error metadata was temporally stopped to ensure that it was still compatible with Merlin, but I am planning to get back to in for 4.14 . Also I would be quite keen to discuss potential use cases to ensure that the produced json is useful for tools.

Concerning, error submessages, I didn't know that lsp/merlin was using them successfully. But yes, if there is such an use case, it would help motivate a more consistent use of submessages in the compiler. Note that as an experiment, the new functor diffing error message in 4.13.0 already uses suberror messages in the functor application case. However, for functors (and any module level error really), a tree structure would have been more natural than a list of submessages at least from the producer side. I would expect that tools could also benefit from such a tree of error messages, but this seems worth discussing in term of design.

### Rudi Grinberg then said

A tree structure sounds like the right thing to do conceptually. But at least in lsp, errors are permitted to have a flat list of "related" messages with locations. That fits the current data error data structure used by OCaml. If a tree was used, I would probably have to flatten it anyways.

## OCaml 4.13.0, first alpha release

### octachron announced

Three months after the release of OCaml 4.12.0, the set of new features for the future version 4.13.0 of OCaml has been frozen. I am thus happy to announce the first alpha release for OCaml 4.13.0 .

This alpha version is here to help fellow hackers join us early in our bug hunting and opam ecosystem fixing fun (see below for the installation instructions). You can see the progress on this front at

If you find any bugs, please report them here: https://github.com/ocaml/ocaml/issues

Once most major OCaml tools are supported, we will switch to beta releases. The full release is expected to happen in September.

If you are interested by the ongoing list of new features and bug fixes, the updated change log for OCaml 4.13.0 is available at:

Note that there is still some on-going work to support improved polling points in preparation for OCaml multicore. Another alpha release will be published once this work is merged.

#### Installation instructions

The base compiler can be installed as an opam switch with the following commands

```opam update
opam switch create 4.13.0~alpha1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git
```

If you want to tweak the configuration of the compiler, you can switch to the option variant with:

```opam update
opam switch create <switch_name> --packages=ocaml-variants.4.13.0~alpha1+options,<option_list>
--repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git
```

where <option_list> is a comma separated list of ocaml-option-* packages. For instance, for a flambda and no-flat-float-array switch:

```opam switch create 4.13.0~alpha1+flambda+nffa
--packages=ocaml-variants.4.13.0~alpha1+options,ocaml-option-flambda,ocaml-option-no-flat-float-array
--repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git
```

All available options can be listed with "opam search ocaml-option".

If you want to test this version, it is advised to install the alpha opam repository at https://github.com/kit-ty-kate/opam-alpha-repository

with

```opam repo add alpha git://github.com/kit-ty-kate/opam-alpha-repository.git
```

This alpha repository contains various fixes in the process of being upstreamed.

The source code for the alpha is also available at these addresses:

## Spin 0.8.0

### Thibaut Mattio announced

I'm happy to announce a new version of `Spin`, the OCaml project generator.

This version comes with a lot of improvements. I'm joining the Changelog below, but I'll highlight some of them here.

#### Spin as an Opam plugin

This version of Spin is available as an Opam plugin.

`opam spin new cli`, for instance, will generate a new CLI.

#### The `hello` command

This release comes with a brand new template targetted solely at first-time users.

The `spin hello` command will generate an hello world project where the development setup and directory structure are explained in the README.

Each file are extensively documented, so users can just open any file and learn by example.

If you're onboarding new users, I'd be curious what's your experience with `opam spin hello`!

#### Simplified templates

The templates have been simplified.

Some templates supported some very specific use cases, such as deploying a CLI on NPM. This is no longer the case and the focus for the official templates from now on will be to support the recommended setup (ie. the OCaml Platform) only.

Part of this simplification is also achieved by dropping the support for Reason and Esy. The previous templates will be available at (https://github.com/ocaml-templates) with the `reason-` prefix.

I've extracted them already, but they will need some reworking before they are usable again.

#### Better prompts

The interactive prompts have been improved through a complete rewrite of `inquire`, the prompt library used in Spin.

I've tried to test the new prompts as much as possible, but if you encounter an issue with them, don't hesitate to open an issue on Spin or Inquire.

#### Dream template

Not really part of this release, because this is a community template, but I have been working on a template for Dream, the new kid OCaml web framework scene, by @aantron.

To try it, you can run: `opam spin new https://github.com/ocaml-templates/spin-dream`.

It comes with a modern setup, including:

• TailwindCSS integrated with Dune
• Inter fonts

It's a bit heavy for my taste at the moment, so I will work on making most of the features optionnal, but if you're looking to start a new Dream app quickly, this might be useful.

#### Changelog

Here's the complete Changelog.

• Added an `hello` command to generate a tutorial project
• Added a `parse_binaries` stanza that can be `true` to force Spin to parse binary files
• Added a `raw_files` stanza that takes a list of file or glob expressions to instruct Spin to copy files instead of parsing them
• Added a new `c-bindings` template for C bindings using `ctypes`
• Added a new `js` template for javascript applications with `js_of_ocaml`
##### Changed
• Removed the `gen` subcommand. The generators will come back with a much better workflow
• Dropped support for Esy and Reason. The templates are now using the recommended OCaml setup only. The previous templates are hosted at https://github.com/ocaml-templates/
• Changed the templates to use the `ISC` license
• Increase version of `ocamlformat` to `0.18.0` in templates
• Do not install merlin when installing dev dependencies in templates
• Drop support for BuckleScript in PPX
• Drop support for publishing on NPM for CLI and PPX templates
• Update CI scripts to `ocaml/setup-ocaml@v2`
• Remove python dependency to serve documentation in Makefile
• Inline release script in Makefile
• Remove global `-open StdLabels` in templates
• The `spa` template has been removed from the official templates and now lives at https://github.com/ocaml-templates/spin-incr-dom
• Spin does not parse binary files by default anymore, they are simply copied to the destination folder
• Use `test` stanza for unit tests now that Alcotest prints colors by default
• Remove unused flags defined in the root's `dune` file
##### Fixes
• The project generation will now fail before the configurations prompt if the output directory is not empty
• By default, Spin now creates a local switch for the generated projects. This can be changed with `spin config`, or by setting the env variable `SPIN_CREATE_SWITCH=false`
• Fix an CLI incompatibility between `opam.2.0.X` and `opam.2.1.X` that made Spin unusable with the former.

I'm also taking the occasion to mention that I am looking for a co-maintainer. If you're interested in improving OCaml tooling and think Spin is a good addition to OCamlers' toolchain, please DM me :)

## vec 0.3.0

### Alex Ionescu announced

I’ve just released version `0.3.0` of `vec` , a library for safe dynamic arrays with Rust-like mutability permissions.

You can find the package on opam here, and the source repository here.

Based on recent feedback, I've revised the API to have more consistent permissions, following some simple rules:

• Reading basic properties (`length`, `capacity`, `growth_rate`) requires no permissions
• Operations that return or indirectly give access to the vector's elements (i.e. by passing them to a user-provided function) require read permission
• Operations that mutate the vector's state (including modifying its elements, resizing its buffer or modifying growth rate) require write permission

I've also added some new APIs for inserting and removing elements at arbitrary indexes, and reworked how `ensure_capacity` works: Now `ensure_capacity n v` ensures that `v`'s buffer has at least `n` free slots.

Please let me know if you have any feedback or suggestions!

## First release of line_oriented

### UnixJunkie announced

A very small library to treat files with lines of text like string lists. https://github.com/UnixJunkie/line-oriented

The interface is here: https://github.com/UnixJunkie/line-oriented/blob/main/src/line_oriented.mli

To get it:

```opam install line_oriented
```

## 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 look at the archive or the RSS feed of the archives.

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