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: $ for array length in index #16231

Closed
zanesterling opened this issue Jun 30, 2016 · 6 comments
Closed

proposal: $ for array length in index #16231

zanesterling opened this issue Jun 30, 2016 · 6 comments

Comments

@zanesterling
Copy link

Negative indexing is a common request from / point of contention for new Go programmers, and has been for nearly seven years.
(2015, 2013, 2011, 2009)
The main argument for is ease of access, while the main argument against is that it introduces risk of insidious bugs where an unintentionally negative index can drastically (and silently) change the properties of a slice.

I haven't seen any mention of how D does things, which is to make $ an alias for the length of the array/slice anywhere between brackets. For example:

auto arr = [1, 2, 3, 4, 5];
writeln(arr[0 .. $]) // [1, 2, 3, 4, 5]
writeln(arr[1 .. $ - 2]) // [2, 3]
writeln(arr[$ - 2 .. $]) // [4, 5]
writeln(arr[$ - 1]) // 5

Written in go syntax:

arr := []int{1, 2, 3, 4, 5}
fmt.Println(arr[0:$]) // [1, 2, 3, 4, 5]
fmt.Println(arr[1:$ - 2] // [2, 3]
fmt.Println(arr[$ - 2:$]) // [4, 5]
fmt.Println(arr[$ - 1]) // 5

This alias allows for pleasantly terse and readable slicing without risk of off-by-one errors causing silent errors. It also enables idiomatic single-line grabs, eg. taking the last element in a csv row: fmt.Println(strings.Split(row, ",")[$ - 1]).

@ianlancetaylor
Copy link
Contributor

I would be loath to add a new character to the language just to avoid writing len(arr). Go is not Perl.

@ianlancetaylor ianlancetaylor added this to the Proposal milestone Jun 30, 2016
@griesemer
Copy link
Contributor

griesemer commented Jun 30, 2016

I'm reasonably sure that we discussed this when designing slices, and decided against it, for a variety of reasons:

  • $ is yet another thing to learn about the language
  • it's not pretty (but I admit that's subjective)
  • len(s) is very efficiently translated by the compiler (just a load from s)
  • if len(s) appears frequently in an expression (which is not uncommon), it's trivial to add a local variable (e.g., n := len(s))
  • more often than not, what you actually want it $-1 rather than $ - which is another reason for a local variable instead

I am voting against this proposal.

@beoran
Copy link

beoran commented Jun 30, 2016

If you have an international keyboard, you can almost have what you want ;)

https://play.golang.org/p/1gLKkNVcS_

@zanesterling
Copy link
Author

The purpose of adding the alias is less to simplify the slice range (although I still contend that it's easier to read), and more to make one-line operations possible.
For this purpose n := len(s) is actually of negative value, as it turns what should take one line and does take two into a full three lines to do something as simple as "take the last token in this space-separated string".

@ianlancetaylor
Copy link
Contributor

@Shriken Being able to write the shortest possible code is not really a goal of Go. While in general shorter is better than longer, clarity and simplicity are more important.

@adg
Copy link
Contributor

adg commented Jul 19, 2016

Given the general negative response to this proposal, I am declaring it "declined." The comments above provide sufficient rationale for this decision.

@adg adg closed this as completed Jul 19, 2016
@golang golang locked and limited conversation to collaborators Jul 19, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants