Typo in Base.List documentation


val sort : compare:('a ‑> 'a ‑> int) ‑> 'a t ‑> 'a t

However, the signature in the list.mli file is in a different order:

val sort : 'a t -> compare:('a -> 'a -> int) -> 'a t

I reckon that’s because latest actually refers to the latest “stable” release, not just the master branch on GitHub. You can see the latest stable release here: https://github.com/janestreet/base/blob/v0.11/src/list.mli#L150, which matches the online docs.

This is the evolution of Base.List.sort:

commit 0cb1db3661ead173df0b3e54a515d07e438221ee
Author: Xavier Clerc <xclerc@janestreet.com>
Date:   Thu Aug 30 10:15:44 2018 +0100


diff --git a/src/list.mli b/src/list.mli
--- a/src/list.mli
+++ b/src/list.mli
@@ -156,1 +156,1 @@
-val sort : compare:('a -> 'a -> int) -> 'a t -> 'a t
+val sort : 'a t -> compare:('a -> 'a -> int) -> 'a t

commit 52a0d80558a2884571435e2c6a1682d984fa0141
Author: Thomas Refis <thomas.refis@gmail.com>
Date:   Fri Mar 16 15:08:08 2018 +0000


diff --git a/src/list.mli b/src/list.mli
--- a/src/list.mli
+++ b/src/list.mli
@@ -150,1 +150,1 @@
-val sort : cmp:('a -> 'a -> int) -> 'a t -> 'a t
+val sort : compare:('a -> 'a -> int) -> 'a t -> 'a t

commit 01cd6e6e0b13aa80e872f1fd90799a2f083c9ab9
Author: Jeremie Dimino <jdimino@janestreet.com>
Date:   Fri Sep 16 15:04:53 2016 +0100


diff --git a/src/base_list.mli b/src/base_list.mli
--- /dev/null
+++ b/src/base_list.mli
@@ -0,0 +137,1 @@
+val sort : cmp:('a -> 'a -> int) -> 'a t -> 'a t

This function was introduced 2016. I would be interested to hear from the maintainers of this stdlib if it’s considered good practise to make such breaking changes to a function that is more than 2 years old. What about all the code that relied upon the order of arguments? Do you provide some kind of migration tool when you make breaking changes in your stdlib?

This kind of migration within Base/Core obviously intends to improve this lib but participates to the confusion especially experienced by beginners and not so much beginners.
A code libs verification and migration tool would be of great interest, not only for JS lib. Is there such a tool or a tool that can be adapted for that purpose?

A totally reasonable question.

The change from ~cmp to ~compare is indeed a breaking change; the change in ordering much less so, since it’s moving a labeled argument.

Base is overall quite stable, but we’ve been waiting to bless a 1.0 version of Base, specifically because there are a number of old mistakes in Core that we wanted to finish before the 1.0 release, at which point we expect to be yet more conservative about making breaking API changes.

The stability issue is also discussed on this page: https://opensource.janestreet.com/base/


Based on a search for "Open Base" "List.sort" at Github, it looks like it’s quite common, to rely upon the order of arguments, i.e. calling List.sort without using the ~compare label. Here are a few examples:

github.com /mzp/dominion/blob/2fcc3b2ce5113594378b480be4f1394c041e8ce6/core/listUtil.ml

    +> List.sort (fun (x,_) (y,_) -> compare x y)

github.com /wallymathieu/XDuce/blob/409477693407ee460a9c28c1fae64a6623683e38/src/addon/loadbib.ml

(List.sort (fun (n,_) (n',_) -> compare n n')

github.com /mbouaziz/geneweb/blob/31019cf95d59d23e8c2e16d730ec21ff3ffa48fc/src/mostdesc.ml

          List.sort f m_list.val;

Even if a library is pre-1.0, it might get a lot of users anyway (e.g. OpenSSL, which was in version 0.9.x for 12 years from 1998 until 2010 when they finally released 1.0.0).

I was about to suggest to take inspiration from Rust, where they have the concept of stable, beta and nightly, but I just read it looks like they are not that strict any longer about not making breaking changes when reading this discussion: https://www.reddit.com/r/rust/comments/9hf2qy/the_future_of_rusts_backwards_compatibility/?st=jp7btmhl&sh=1d56d2e7

At least one good example is Linux, in the words of Linus Torvalds:

Breaking user programs simply isn’t acceptable. (…) We know that people use old binaries for years and years, and that making a new release doesn’t mean that you can just throw that out. You can trust us.

One thing that would be awesome would be a transpiler conversion tool that would automatically convert OCaml using the previous version of Base/Core to the next version. That would reduce the manual time required to make the changes to O(1) instead of O(n) where n is the size of the code base. Such a tool would be useful even post-1.0, to help users migrate away from obsolete functions. If anyone would be willing to work on such a tool, I’m willing to contribute both time-wise doing testing, but also financially, to make that happen.

1 Like

As an aside, I don’t think the linked examples are using base or core.

My bad, Base seems to be a popular module name in projects.

I searched for open Core instead, and all of the example I could find were using the ~cmp or ~compare label, so I was wrong about code relying upon the order of arguments, I couldn’t find a single example for Core.