Dear SML people,
There is an OCaml feature proposal by Alistair O'Brien that would finally introduce tuple indexing in OCaml -- we currently have only whole-tuple pattern matching:
RFC: https://github.com/johnyob/ocaml-RFCs/blob/tuple-projections/rfcs/tuple_proj... discussion: https://github.com/ocaml/RFCs/pull/57
Of course this raises the Very Important Question of whether indexing should be 0-based or 1-based.
The argument in favor of 0-based is that it is what we use for arrays, so more consistent, standard in most programming languages. The argument in favor of 1-based is that it is arguably more intuitive (but the inconsistency with arrays weakens this claim noticeably), and that SML uses it.
Question: you have a lot more experience using tuple indexing. In your opinion, if this was to be decided again for a new system (no backward-compatibility concerns), would you still recommend using 1-based indices, or would you be more in favor of 0-based indices?
P.S.: You may be amused to learn that OCaml recently introduced "labeled tuples" (looking like `(x:1, y:2)` in expressions and `(x:int * y:int)` in types), which are basically a restricted version of SML structural records -- type inference does not try very hard and requires an annotation in practice.
P.P.S: Is there still a mailing-list for the SML/NJ crowd? All I could find were github discussions (https://github.com/orgs/smlnj/discussions) and an invite-only Zulip.
Yay to that!!
From my perspective, the main reason in favour of 1-based is that programmers almost universally write
let f (x1, x2) = ...
today, so the 1-based convention already is everywhere. IME it's quite confusing when such code is mixed with uses of a projection operator based on a different numbering scheme, which is inevitable in practice.
The comparison with arrays is less important IMO, since tuple indices are just static names and not computed, so rather different beasts.
That said, I don’t have a super-strong opinion here, just give me e.i already. :)
Cheers, /Andreas
On 25. Oct 2025, at 14:32, Gabriel Scherer gabriel.scherer@inria.fr wrote:
Dear SML people,
There is an OCaml feature proposal by Alistair O'Brien that would finally introduce tuple indexing in OCaml -- we currently have only whole-tuple pattern matching:
RFC: https://github.com/johnyob/ocaml-RFCs/blob/tuple-projections/rfcs/tuple_proj... discussion: https://github.com/ocaml/RFCs/pull/57
Of course this raises the Very Important Question of whether indexing should be 0-based or 1-based.
The argument in favor of 0-based is that it is what we use for arrays, so more consistent, standard in most programming languages. The argument in favor of 1-based is that it is arguably more intuitive (but the inconsistency with arrays weakens this claim noticeably), and that SML uses it.
Question: you have a lot more experience using tuple indexing. In your opinion, if this was to be decided again for a new system (no backward-compatibility concerns), would you still recommend using 1-based indices, or would you be more in favor of 0-based indices?
P.S.: You may be amused to learn that OCaml recently introduced "labeled tuples" (looking like `(x:1, y:2)` in expressions and `(x:int * y:int)` in types), which are basically a restricted version of SML structural records -- type inference does not try very hard and requires an annotation in practice.
P.P.S: Is there still a mailing-list for the SML/NJ crowd? All I could find were github discussions (https://github.com/orgs/smlnj/discussions) and an invite-only Zulip.
On 25/10/2025 14:32, Gabriel Scherer wrote:
The argument in favor of 0-based is that it is what we use for arrays, so more consistent, standard in most programming languages. The argument in favor of 1-based is that it is arguably more intuitive (but the inconsistency with arrays weakens this claim noticeably), and that SML uses it.
Question: you have a lot more experience using tuple indexing. In your opinion, if this was to be decided again for a new system (no backward- compatibility concerns), would you still recommend using 1-based indices, or would you be more in favor of 0-based indices?
I am normally a purist in counting almost everything from 0, but for tuples I would not do it. It just asking for too much trouble, in conflict with usual mathematical customs like (x1, x2, x3, x4) etc. Think of old-fashioned vectors and matrices.
Speaking abstractly, consistency is a high value not to be given up lightly, but there are often situations, where special rules should apply to a certain "curpus separatum".
Makarius
On Oct 25, 2025, at 19:32, Gabriel Scherer gabriel.scherer@inria.fr wrote:
Dear SML people,
There is an OCaml feature proposal by Alistair O'Brien that would finally introduce tuple indexing in OCaml -- we currently have only whole-tuple pattern matching:
RFC: https://github.com/johnyob/ocaml-RFCs/blob/tuple-projections/rfcs/tuple_proj... discussion: https://github.com/ocaml/RFCs/pull/57
Of course this raises the Very Important Question of whether indexing should be 0-based or 1-based.
The argument in favor of 0-based is that it is what we use for arrays, so more consistent, standard in most programming languages. The argument in favor of 1-based is that it is arguably more intuitive (but the inconsistency with arrays weakens this claim noticeably), and that SML uses it.
Question: you have a lot more experience using tuple indexing. In your opinion, if this was to be decided again for a new system (no backward-compatibility concerns), would you still recommend using 1-based indices, or would you be more in favor of 0-based indices?
I think that base-1 indexing makes more sense, since it matches the usual projection/indexing found in common mathematical usage. I think tuples and arrays are pretty different, so I don't see consistency as being crucial. You are not going to be doing index arithmetic on tuple indices, they are really just labels.
FYI, I think zero-based array indexing is an artifact of the fact that early C did not really have arrays; it just had syntactic sugar for pointer arithmetic. Fortran had (has?) 1-based indices and Algol and Pascal had arbitrary base indices.
P.S.: You may be amused to learn that OCaml recently introduced "labeled tuples" (looking like `(x:1, y:2)` in expressions and `(x:int * y:int)` in types), which are basically a restricted version of SML structural records -- type inference does not try very hard and requires an annotation in practice.
P.P.S: Is there still a mailing-list for the SML/NJ crowd? All I could find were github discussions (https://github.com/orgs/smlnj/discussions) and an invite-only Zulip.
The smlnj-dev-list@mailman.cs.uchicago.edu mailto:smlnj-dev-list@mailman.cs.uchicago.edu list is still used to announce releases, but we've mostly switched to using GitHub for communication. David MacQueen manages the Zulip, which I don't follow very closely.
- John
* John Reppy:
FYI, I think zero-based array indexing is an artifact of the fact that early C did not really have arrays; it just had syntactic sugar for pointer arithmetic. Fortran had (has?) 1-based indices and Algol and Pascal had arbitrary base indices.
On the other hand, if your language supports array slices (non-copying subarrays) and these slices preserve the original indices, you are effectively back to zero-based indexing: you have to access relative to the starting index of the slice, so the first element is at zero. Ada is like that, array slice elements go from Slice (Slice'First), Slice (Slice'First + 1) up to Slice (Slice'First + Slice'Length - 1). This is a bit strange because Ada arrays start at index 1.
I'm also in favor of 1-based tuples. Adding one other argument: I've never seen an extension of the lambda calculus with pairs that introduces projects `zth` and `fst`; it's always `fst` and `snd`.
-Matthew
On Mon, Oct 27, 2025 at 4:46 AM Florian Weimer fw@deneb.enyo.de wrote:
- John Reppy:
FYI, I think zero-based array indexing is an artifact of the fact that early C did not really have arrays; it just had syntactic sugar for pointer arithmetic. Fortran had (has?) 1-based indices and Algol and Pascal had arbitrary base indices.
On the other hand, if your language supports array slices (non-copying subarrays) and these slices preserve the original indices, you are effectively back to zero-based indexing: you have to access relative to the starting index of the slice, so the first element is at zero. Ada is like that, array slice elements go from Slice (Slice'First), Slice (Slice'First + 1) up to Slice (Slice'First + Slice'Length - 1). This is a bit strange because Ada arrays start at index 1. _______________________________________________ Poly/ML mailing list -- polyml@lists.polyml.org To unsubscribe send an email to polyml-leave@lists.polyml.org
Yes, for order numbers it is more natural in plain English to use first than zeroth.
Zero comes more naturally at e.g. a geometric sequence, a_i = a * q^n, then a_0 = a, this is more natural. But in a tuple we do not compute with the indices, they just select an element which might be some other type than the other ones.
- Gergely
On Mon, 27 Oct 2025 at 14:25, Matthew Fluet matthew.fluet@gmail.com wrote:
I'm also in favor of 1-based tuples. Adding one other argument: I've never seen an extension of the lambda calculus with pairs that introduces projects `zth` and `fst`; it's always `fst` and `snd`.
-Matthew
On Mon, Oct 27, 2025 at 4:46 AM Florian Weimer fw@deneb.enyo.de wrote:
- John Reppy:
FYI, I think zero-based array indexing is an artifact of the fact that early C did not really have arrays; it just had syntactic sugar for pointer arithmetic. Fortran had (has?) 1-based indices and Algol and Pascal had arbitrary base indices.
On the other hand, if your language supports array slices (non-copying subarrays) and these slices preserve the original indices, you are effectively back to zero-based indexing: you have to access relative to the starting index of the slice, so the first element is at zero. Ada is like that, array slice elements go from Slice (Slice'First), Slice (Slice'First + 1) up to Slice (Slice'First + Slice'Length - 1). This is a bit strange because Ada arrays start at index 1. _______________________________________________ Poly/ML mailing list -- polyml@lists.polyml.org To unsubscribe send an email to polyml-leave@lists.polyml.org
Poly/ML mailing list -- polyml@lists.polyml.org To unsubscribe send an email to polyml-leave@lists.polyml.org
This would be a good discussion to carry on at standardml.zulipchat.com http://standardml.zulipchat.com/! I established that Zulip “organization” for just such discussions, which may as well be carried out “in public” in some sense.
Anyway, my 2 cents about tuples:
In general mathematical discourse, I believe it is common to talk about the “first”, “second”, etc. element of a tuple, where a tuple is an element of an n-ary product (and where the product is typically homogenious, e.g. R * R * R, rather than R * I * B. In ISWIM and LCF/ML, one uses the projection names “fst”, “snd” for projecting from a binary product (the only “arity” of product supported), which suggests numbering the components of a pair as 1 and 2. We saw no point in diverging from this common practice in Standard ML; hence tuple projections are #1, #2, etc.
One SML design choice that I have come to feel uncomfortable about (perhaps I always did) is viewing tuples as records with natural number _labels_. I.e. (3, true) = {1 = 3, 2 = true}. This allows anomalous things like {1 = 3, 17 = true}, which is an odd sort of record with numberic labels but which is not a tuple. In fact, in my planned New Front End project, I plan to break with this treatment and view tuples as standing on their own, not as special sorts of record. Merging tuples into records produced some simplification in implementation (not having to support tuples per se in the abstract syntax, for instance), but at the cost of a bit of “tricky-ness”. This issue is orthogonal about how we choose to number the elements of a tuple.
[By the way, I wrote the proposal on records and tuples during the SML design discussions.]
Dave
On Oct 27, 2025, at 7:47 AM, Gergely Buday g.buday@sheffield.ac.uk wrote:
Yes, for order numbers it is more natural in plain English to use first than zeroth.
Zero comes more naturally at e.g. a geometric sequence, a_i = a * q^n, then a_0 = a, this is more natural. But in a tuple we do not compute with the indices, they just select an element which might be some other type than the other ones.
- Gergely
On Mon, 27 Oct 2025 at 14:25, Matthew Fluet matthew.fluet@gmail.com wrote:
I'm also in favor of 1-based tuples. Adding one other argument: I've never seen an extension of the lambda calculus with pairs that introduces projects `zth` and `fst`; it's always `fst` and `snd`.
-Matthew
On Mon, Oct 27, 2025 at 4:46 AM Florian Weimer fw@deneb.enyo.de wrote:
- John Reppy:
FYI, I think zero-based array indexing is an artifact of the fact that early C did not really have arrays; it just had syntactic sugar for pointer arithmetic. Fortran had (has?) 1-based indices and Algol and Pascal had arbitrary base indices.
On the other hand, if your language supports array slices (non-copying subarrays) and these slices preserve the original indices, you are effectively back to zero-based indexing: you have to access relative to the starting index of the slice, so the first element is at zero. Ada is like that, array slice elements go from Slice (Slice'First), Slice (Slice'First + 1) up to Slice (Slice'First + Slice'Length - 1). This is a bit strange because Ada arrays start at index 1. _______________________________________________ Poly/ML mailing list -- polyml@lists.polyml.org To unsubscribe send an email to polyml-leave@lists.polyml.org
Poly/ML mailing list -- polyml@lists.polyml.org To unsubscribe send an email to polyml-leave@lists.polyml.org
David MacQueen dmacqueen@mac.com
On 28. Oct 2025, at 03:29, David MacQueen dmacqueen@mac.com wrote:
This would be a good discussion to carry on at standardml.zulipchat.com! I established that Zulip “organization” for just such discussions, which may as well be carried out “in public” in some sense.
Anyway, my 2 cents about tuples:
In general mathematical discourse, I believe it is common to talk about the “first”, “second”, etc. element of a tuple, where a tuple is an element of an n-ary product (and where the product is typically homogenious, e.g. R * R * R, rather than R * I * B. In ISWIM and LCF/ML, one uses the projection names “fst”, “snd” for projecting from a binary product (the only “arity” of product supported), which suggests numbering the components of a pair as 1 and 2. We saw no point in diverging from this common practice in Standard ML; hence tuple projections are #1, #2, etc.
One SML design choice that I have come to feel uncomfortable about (perhaps I always did) is viewing tuples as records with natural number _labels_. I.e. (3, true) = {1 = 3, 2 = true}. This allows anomalous things like {1 = 3, 17 = true}, which is an odd sort of record with numberic labels but which is not a tuple.
I don’t see an issue with numeric records that don’t correspond to a tuple. But I always disliked the fact that numeric records contain seemingly absurd equations like `1 = 3`. That could easily be fixed by changing the syntax of numeric labels, e.g., to `_1` (or `~1` as OCaml would now, if you enjoy that particular syntax).
But we’re digressing. :)
As for tuple indexing in OCaml, the fact that OCaml itself already has functions named `fst` and `snd` perhaps is another good reason to stick to the 1-based convention.
In fact, in my planned New Front End project, I plan to break with this treatment and view tuples as standing on their own, not as special sorts of record. Merging tuples into records produced some simplification in implementation (not having to support tuples per se in the abstract syntax, for instance), but at the cost of a bit of “tricky-ness”. This issue is orthogonal about how we choose to number the elements of a tuple.
[By the way, I wrote the proposal on records and tuples during the SML design discussions.]
Dave
On Oct 27, 2025, at 7:47 AM, Gergely Buday g.buday@sheffield.ac.uk wrote:
Yes, for order numbers it is more natural in plain English to use first than zeroth.
Zero comes more naturally at e.g. a geometric sequence, a_i = a * q^n, then a_0 = a, this is more natural. But in a tuple we do not compute with the indices, they just select an element which might be some other type than the other ones.
- Gergely
On Mon, 27 Oct 2025 at 14:25, Matthew Fluet matthew.fluet@gmail.com wrote:
I'm also in favor of 1-based tuples. Adding one other argument: I've never seen an extension of the lambda calculus with pairs that introduces projects `zth` and `fst`; it's always `fst` and `snd`.
-Matthew
On Mon, Oct 27, 2025 at 4:46 AM Florian Weimer fw@deneb.enyo.de wrote:
- John Reppy:
FYI, I think zero-based array indexing is an artifact of the fact that early C did not really have arrays; it just had syntactic sugar for pointer arithmetic. Fortran had (has?) 1-based indices and Algol and Pascal had arbitrary base indices.
On the other hand, if your language supports array slices (non-copying subarrays) and these slices preserve the original indices, you are effectively back to zero-based indexing: you have to access relative to the starting index of the slice, so the first element is at zero. Ada is like that, array slice elements go from Slice (Slice'First), Slice (Slice'First + 1) up to Slice (Slice'First + Slice'Length - 1). This is a bit strange because Ada arrays start at index 1. _______________________________________________ Poly/ML mailing list -- polyml@lists.polyml.org To unsubscribe send an email to polyml-leave@lists.polyml.org
Poly/ML mailing list -- polyml@lists.polyml.org To unsubscribe send an email to polyml-leave@lists.polyml.org
David MacQueen dmacqueen@mac.com