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

Comments

Projects
None yet
@posener

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

This comment has been minimized.

Show comment
Hide comment
@jimmyfrasche

jimmyfrasche Apr 29, 2017

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

Member

jimmyfrasche commented Apr 29, 2017

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

This comment has been minimized.

Show comment
Hide comment
@mvdan

mvdan Apr 29, 2017

Member

Good point @jimmyfrasche - will label the issue appropriately.

Member

mvdan commented Apr 29, 2017

Good point @jimmyfrasche - will label the issue appropriately.

@mvdan mvdan added this to the Proposal milestone Apr 29, 2017

@mvdan

This comment has been minimized.

Show comment
Hide comment
@mvdan

mvdan Apr 29, 2017

Member

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.

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

This comment has been minimized.

Show comment
Hide comment
@mdempsky

mdempsky Apr 30, 2017

Member

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.

Member

mdempsky commented Apr 30, 2017

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

This comment has been minimized.

Show comment
Hide comment
@posener

posener 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

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

This comment has been minimized.

Show comment
Hide comment
@mdempsky

mdempsky Apr 30, 2017

Member

@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.

Member

mdempsky commented Apr 30, 2017

@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

This comment has been minimized.

Show comment
Hide comment
@posener

posener Apr 30, 2017

@mdempsky totally agree 👍

posener commented Apr 30, 2017

@mdempsky totally agree 👍

@josharian

This comment has been minimized.

Show comment
Hide comment
@josharian

josharian Apr 30, 2017

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?).
Contributor

josharian commented Apr 30, 2017

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

This comment has been minimized.

Show comment
Hide comment
@urandom

urandom 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.

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

This comment has been minimized.

Show comment
Hide comment
@bradfitz

bradfitz May 8, 2017

Member

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.

Member

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

This comment has been minimized.

Show comment
Hide comment
@josharian

josharian May 8, 2017

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.

Contributor

josharian commented May 8, 2017

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

This comment has been minimized.

Show comment
Hide comment
@akavel

akavel May 10, 2017

Contributor

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.

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 from proposal: len keyword inside slice/index brackets for string/array/slice to proposal: spec: accept x[len-1] as x[len(x)-1] Jun 16, 2017

@robpike

This comment has been minimized.

Show comment
Hide comment
@robpike

robpike Jun 21, 2017

Contributor

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.

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

This comment has been minimized.

Show comment
Hide comment
@ghasemloo

ghasemloo Jul 12, 2017

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

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

@robpike

This comment has been minimized.

Show comment
Hide comment
@robpike

robpike Jul 12, 2017

Contributor

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

Contributor

robpike commented Jul 12, 2017

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

@ghasemloo

This comment has been minimized.

Show comment
Hide comment
@ghasemloo

ghasemloo Jul 12, 2017

Sorry, missed that.

Sorry, missed that.

@golang golang deleted a comment from Allthewaylive247 Jul 12, 2017

@ianlancetaylor

This comment has been minimized.

Show comment
Hide comment
@ianlancetaylor

ianlancetaylor Feb 13, 2018

Contributor

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.

Contributor

ianlancetaylor commented Feb 13, 2018

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 join this conversation on GitHub. Already have an account? Sign in to comment