i don't remember the answer to your question, but I suspect it is this:

# 1,2 ;;
- : int * int = (1, 2)

That is, again, syntactic succinctness.  tuples need not always be parenthesized.  But I'm really just making this up -- I certainly don't remember well enough to be definitive on this.

It does seem to follow the general pattern, though: with generativity of record-field-names as another example.

On Wed, Feb 14, 2018 at 3:40 PM, Ian Zimmerman <itz@very.loosely.org> wrote:
On 2018-02-14 15:02, Chet Murthy wrote:

> I remember back in the day Pierre Weis explaining to me that this
> syntactic trade-off was made in order to allow that "let" and "match"
> didn't have ending key-words (e.g. "end").

I would understand and accept that choice.  But the larger question is,
why was the semicolon overloaded like this?  In SML the semicolon serves
just one purpose: separating consecutive imperative statements (well it
can also separate declarations but that is optional).  Why has CAML
chosen to use the semicolon in list and record patterns and values,
instead of the comma like SML?

> Unlike in SML/NJ.

SML has multiple implementations (as implied in the S).