Skip to content
New issue

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

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

Already on GitHub? # to your account

proposal: spec: for int, *E := range *[]E #69337

Closed
1 of 4 tasks
myaaaaaaaaa opened this issue Sep 7, 2024 · 3 comments
Closed
1 of 4 tasks

proposal: spec: for int, *E := range *[]E #69337

myaaaaaaaaa opened this issue Sep 7, 2024 · 3 comments
Labels
LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal
Milestone

Comments

@myaaaaaaaaa
Copy link

myaaaaaaaaa commented Sep 7, 2024

Go Programming Experience

Experienced

Other Languages Experience

C, C++, Python, Javascript

Related Idea

  • Has this idea, or one like it, been proposed before?
  • Does this affect error handling?
  • Is this about generics?
  • Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit

Has this idea, or one like it, been proposed before?

Unlike the above proposal, which requires new syntax and is non-orthogonal, this one aims to accomplish the same thing by just adding a new supported type to range.

Proposal

Currently, ranging over slices and arrays only provides read access since the elements are copied by value. Adding a way to modify them when using range would enable loops to omit using index variables entirely for most cases, apart from the rare cases when index arithmetic is actually necessary.

This would, among other things, prevent accidentally using the wrong index when writing nested loops.

func ExampleRange() {
	nums := make([]int, 5)


	for _, n := range nums {
		n = 2 // n is a copy so this doesn't modify the slice
	}
	fmt.Println(nums)
	//Output:
	//[0 0 0 0 0]


	for _, n := range &nums {
		*n = 2 // Proposed solution
	}
	fmt.Println(nums)
	//Output:
	//[2 2 2 2 2]
}

Language Spec Changes

 Range expression                                              1st value                2nd value
 
-array or slice             a  [n]E, *[n]E, or []E             index    i  int          a[i]       E
+array or slice             a  [n]E, or []E                    index    i  int          a[i]       E
+pointer to array or slice  p  *[n]E, or *[]E                  index    i  int          &p[i]      *E
 string                     s  string type                     index    i  int          see below  rune
 map                        m  map[K]V                         key      k  K            m[k]       V
 channel                    c  chan E, <-chan E                element  e  E
 integer value              n  integer type, or untyped int    value    i  see below
 function, 0 values         f  func(func() bool)
 function, 1 value          f  func(func(V) bool)              value    v  V
 function, 2 values         f  func(func(K, V) bool)           key      k  K            v          V

Informal Change

N/A

Is this change backward compatible?

Unfortunately Go already supports ranging over array pointers (!), so this would change the behavior of such loops. A gofix rule should be able to update affected loops:

 for i, v := range arrayPtr {
+	v := *v

 	// ...
 }

Slice pointers are new and therefore backward compatible.

Orthogonality: How does this change interact or overlap with existing features?

This change arguably increases orthogonality (compared to the current range-over-array-pointer), since it more closely follows the convention that taking a pointer of a value should allow for modifying it.

Would this change make Go easier or harder to learn, and why?

N/A

Cost Description

Tools that understand the type of the expression in range statements would need to be updated to the new semantics.

Changes to Go ToolChain

vet, gopls

Performance Costs

N/A (likely minimal)

Prototype

N/A

@myaaaaaaaaa myaaaaaaaaa added LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal labels Sep 7, 2024
@gopherbot gopherbot added this to the Proposal milestone Sep 7, 2024
@seankhliao
Copy link
Member

I believe the closing comment for #21537 also applies here, this is just a different syntax but with the same limitations.

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Sep 7, 2024
@ianlancetaylor
Copy link
Member

Also, as the proposal points out, this change is not backward compatible. We are not going to make a language change that causes valid code to have one meaning in release 1.X and a different meaning in release 1.X+1. (We did such a change once, as described at https://go.dev/wiki/LoopvarExperiment, but that was a special case that we aren't going to repeat.)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal
Projects
None yet
Development

No branches or pull requests

5 participants