Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: spec: accept x[len-1] as x[len(x)-1] #20176

Closed
posener opened this issue Apr 29, 2017 · 17 comments
Closed

proposal: spec: accept x[len-1] as x[len(x)-1] #20176

posener opened this issue Apr 29, 2017 · 17 comments
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Milestone

Comments

@posener
Copy link

posener commented Apr 29, 2017

When applying the index or slice operations on a string/array/slice allow the keyword len inside the brackets. In that case len will mean len(a) where a is the referred string/array/slice variable before the brackets.

For example, if s is of string/array/slice type:

  • s[len-1] will be exactly the same as s[len(s)-1]
  • s[len-5:len-2] will be exactly the same as s[len(s)-5:len(s)-2]

Pros:

  • Readability, specially when the variable name is long.
  • Does not add any new keyword to the language.

Cons:

  • Will break programs that use len as variable name.

Related issues:

@jimmyfrasche
Copy link
Member

len is a predeclared identifier not a keyword so this would add a keyword to the language.

This is a currently valid, albeit silly, program that would be made invalid by this proposal: https://play.golang.org/p/jtQ0U9pQ1H

@mvdan
Copy link
Member

mvdan commented Apr 29, 2017

Good point @jimmyfrasche - will label the issue appropriately.

@mvdan mvdan added v2 An incompatible library change LanguageChange Suggested changes to the Go language Proposal labels Apr 29, 2017
@mvdan mvdan added this to the Proposal milestone Apr 29, 2017
@mvdan
Copy link
Member

mvdan commented Apr 29, 2017

As for the proposed change itself, I think it trades less verbosity for language complexity. Like Jimmy pointed out, you're adding a new keyword. And unlike the old len, this new one can act as both a function and an integer value on its own. I'm not sure s[len-1] would read as easily to newcomers as s[len(s)-1], especially when most code uses len as a function.

In the scope of Go2, I feel that verbosity like s[len(s)-1] and s = append(s, ...) could be improved in many ways. I'm not convinced this change would be a net win.

@mdempsky
Copy link
Contributor

len isn't a keyword, but I don't think we need to make it into one for this proposal to work.

It's currently not valid to use builtin functions outside of a call expression. This would simply be a matter of changing it so len is valid by itself in index and slice expression contexts.

@posener
Copy link
Author

posener commented Apr 30, 2017

@jimmyfrasche It wouldn't change the behavior of the program you wrote, because as @mdempsky pointed out, len outside the brackets is still valid, but it would change the following one:

package main

import "fmt"

func main() {
	len := 1
	a := []int{1,2,3}
	fmt.Println(a[len])
}

I'll update the proposal

@mdempsky
Copy link
Contributor

@posener I disagree with changing the meaning of any existing programs. If len is shadowed by a local variable, then a[len] should use that local variable. It should not mean a[len(a)] in that case.

@posener
Copy link
Author

posener commented Apr 30, 2017

@mdempsky totally agree 👍

@josharian
Copy link
Contributor

I don't think this is going to happen. But if it were, a few other things to consider:

  • Side-effects and evaluation order. In f()[len-1], how many times does f get called? Note that this affects whether translating x[len-1] into x[len(x)-1] and back again is a safe transformation.
  • Scoping. This appears to introduce a kind of scope. In a[b[len-1]], I presume len refers to b's len, not a. This is a significant additional burden on tools.
  • cap as well?
  • It's easier to evaluate this kind of suggestion with data. See e.g. the quick-and-dirty exploration of the kinds of for loops people use at https://github.com/josharian/gofor, or the number of select cases people use at https://github.com/josharian/countselectcases.
  • I suspect the most common usage by far of this would be for len(x)-1. In that case, a smaller change would be to use constant negative indices, similar to python: x[-1]. Non-constant negative indices would continue to panic, for bug-catching properties (or not?).

@urandom
Copy link

urandom commented May 7, 2017

Allowing negative indices would cover most of the usages of [len(s)-N]. And since negative indices are pretty common, users wouldn't really be confused by them.

@josharian
Not sure why non-constants should be disallowed. Having [-N] as an index is pretty useful.

@bradfitz
Copy link
Contributor

bradfitz commented May 8, 2017

Making negative indices have special meaning is not going to happen. It's been proposed and rejected a number of times in the past. The rejection reason is that it's too easy to screw up your math and underflow 0 and suddenly get crazy opposite behavior instead of bounds checks runtime errors.

@josharian
Copy link
Contributor

Not that I'm pushing for it, but to be clear, the proposal above was negative constant (or even literal) indices, which I believe mitigates that concern.

@akavel
Copy link
Contributor

akavel commented May 10, 2017

For the record: Lua has a # operator instead of a len function (so one can write s[#s-1], or actually s[#s] given Lua's 1-based indexing). That said, it doesn't have s[#] either. On the other hand, it doesn't have table slicing expressions, nor does it support string indexing using an operator.

@rsc rsc changed the title proposal: len keyword inside slice/index brackets for string/array/slice proposal: spec: accept x[len-1] as x[len(x)-1] Jun 16, 2017
@robpike
Copy link
Contributor

robpike commented Jun 21, 2017

The refinement of allowing negative constants only is interesting and perhaps worth considering. It does add a particularly special and detailed wrinkle, though. There's nothing similar that I can think of that exists already in the language. And because of that, the exact definition will take lots of discussion and bikeshedding. Literal? Constant? Constant expression? What about cap? etc. etc.

I'm not sure it's a good fit, but it is a clever suggestion.

@ghasemloo
Copy link

I think a better proposal would be to accept x[-1] as x[len(x)-1] as in Python.

@robpike
Copy link
Contributor

robpike commented Jul 12, 2017

As explained above by @bradfitz, that's not a good suggestion.

@ghasemloo
Copy link

Sorry, missed that.

@golang golang deleted a comment from Allthewaylive247 Jul 12, 2017
@ianlancetaylor
Copy link
Member

There is no strong support for this specific proposal, and it requires either adding a new keyword or making some very special treatment of the predeclared identifier len. Closing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Projects
None yet
Development

No branches or pull requests