Go: proposal: Go 2: make final index in a three-index slice expression default to the middle index value

Created on 30 May 2018  路  3Comments  路  Source: golang/go

The current three-index slice form index presentation rule quite discourages gophers to use three-index slice forms. The current rule requires the middle and final index must be both represent in a three-index slice form, which makes three-index slice form quite verbose.

For example, many library may contain functions like the following one:

var hiddenOpts = []Option{...}

func NewX(opts ...Option) *X {
    opts := append(opts, hiddenOpts...)
    return createX(opts)
}

The defect (if it is not a bug) of the function NewX is it may modify the underlying data of passed arguments. It is better to use append(opts[:len(opts):len(opts)], hiddenOpts...) instead. But for its verbosity, its uses are limited.

In fact, in practice, when a three-index form is used, the final index is often same as the middle index. In particular, s[ : len(s) : len(s)] is used most often. So I propose the following simplified three-index slice forms:

s[ : n : ]  // <=> s[ : n : n]
s[m : n : ] // <=> s[m : n : n]
s[ : : ]    // <=> s[ : len(s) : len(s)]
s[m : : ]   // <=> s[m : len(s) : len(s)]

So that, we can use append(opts[::], hiddenOpts...) in the above NewX function, without too verbose.

FrozenDueToAge Go2 LanguageChange Proposal

Most helpful comment

Currently in a simple slice expression, with two values, if you omit the first index it is replaced by the lowest possible value (0) and if you omit the second index it is replaced by the highest likely value (len(s)). If we carry that forward to full slice expressions, then if you omit the third index it would be replaced by the highest likely value, which is cap(s). You are suggesting instead that the third index default to the second index. It's a reasonable choice but cap(s) seems just as reasonable. I'm concerned that when there are two reasonable choices, people may easily get confused about which one applies. When there are two reasonable defaults, it seems best to require people to specify which value they mean, as is true today. Also, specifying the capacity is not a common situation, so people will not see it often, and so are less likely to recall what the default is. And, since it is not common, it's not such a big deal that you have to write a bit more to clarify what you mean.

Erring on the side of caution, proposal rejected. Thanks for the suggestion, though.

All 3 comments

I agree that opts[::] is not too verbose, but to be honest I worry that it is too obscure.

Currently in a simple slice expression, with two values, if you omit the first index it is replaced by the lowest possible value (0) and if you omit the second index it is replaced by the highest likely value (len(s)). If we carry that forward to full slice expressions, then if you omit the third index it would be replaced by the highest likely value, which is cap(s). You are suggesting instead that the third index default to the second index. It's a reasonable choice but cap(s) seems just as reasonable. I'm concerned that when there are two reasonable choices, people may easily get confused about which one applies. When there are two reasonable defaults, it seems best to require people to specify which value they mean, as is true today. Also, specifying the capacity is not a common situation, so people will not see it often, and so are less likely to recall what the default is. And, since it is not common, it's not such a big deal that you have to write a bit more to clarify what you mean.

Erring on the side of caution, proposal rejected. Thanks for the suggestion, though.

Just noticed this was declined.

Some final arguments.

Although the absence third index default to cap(s) is also reasonable, but this effect can be also achieved by further omitting the second : (a.k.a., a two-index form supported currently). So I think if the second : presents and the third index is omitted, people would expect a different effect.

In fact, I think the rationale of thinking the absence third index default to cap(s) is from the consideration of consistency. However, there are already many syntax and semantics inconsistencies in Go design. So I think if there is another more reasonable cause, consistency can be a secondary consideration factor in design.

Also, specifying the capacity is not a common situation, so people will not see it often, ...

I think one reason people don't see it often is it is some verbose to written, which is why this proposal was made, :). I can't say this is main reason three-index forms is seldom used, but it really counts for some percentage, about 15%, maybe.

And BTW, this proposal is Go 1 compatible.

Was this page helpful?
0 / 5 - 0 ratings