Skip to content

proposal: spec: Permit range over type sets of rangeable types #71042

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

Closed
4 tasks done
duckbrain opened this issue Dec 27, 2024 · 3 comments
Closed
4 tasks done

proposal: spec: Permit range over type sets of rangeable types #71042

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

Comments

@duckbrain
Copy link

duckbrain commented Dec 27, 2024

Go Programming Experience

Intermediate

Other Languages Experience

No response

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?

No, however there is some overlap in use-cases with #44253

Does this affect error handling?

No

Is this about generics?

Yes, this is lifting a restriction for type sets that contain all rangeable values.

Proposal

Permit using the range operation over a parameterized type set where all types can use the range operation.

For example:

package main

import (
	"cmp"
	"fmt"
)

type List[T cmp.Ordered] interface {
	~[1]T | ~[2]T | ~[3]T | ~[4]T | ~[5]T
}

func CompareLists[T cmp.Ordered, L List[T]](a, b L) int {
	for i := range a {
		if d := cmp.Compare(a[i], b[i]); d != 0 {
			return d
		}
	}
	return 0
}

func main() {
	var a = [...]int{1, 2, 3}
	var b = [...]int{1, 3, 4}

	fmt.Println(CompareLists[int](a, b))
}

Today this code fails to compile with the following message:

./prog.go:13:17: cannot range over a (variable of type L constrained by List[T]): no core type

Per the language specification, range expressions must have specific core types, and type sets of arrays don't have a core type since every size of array is a different underlying type.

Interestingly, both len and the index expression are permitted, so the example code can be rewritten to work using a traditional for loop. This was surprising and it took me reading the language specification to realize that this was another possibility.

func CompareLists[T cmp.Ordered, L List[T]](a, b L) int {
	for i := 0; i < len(a); i++ {
		if d := cmp.Compare(a[i], b[i]); d != 0 {
			return d
		}
	}
	return 0
}

Language Spec Changes

No response

Informal Change

You can now use a range operation on generic types of mixed arrays and slices.

Is this change backward compatible?

Yes

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

No response

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

Yes, currently most operations are permitted on parameterized types that are type sets of types that allow that operation. eg: the arithmetic operations, index expressions, and the built-in len function. This removes what appears to be an exception to that rule.

Cost Description

The specification becomes more complicated since the language can no longer lean on the definition of "core type" to describe which parameterized types may use a range operation.

Changes to Go ToolChain

No response

Performance Costs

No response

Prototype

No response

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

I believe this is part of #70128

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Dec 27, 2024
@duckbrain
Copy link
Author

The nature of #70128 to changed since this was closed, so rather than it encompassing this proposal, it lays foundation for it by removing core types.

Can this be reopened?

The proposal will need updated to remove references to core types and will need to address specifics with which types can be ranged over. Likey, "range can be used if all types in the type set are arrays and slices of the same type". The current "all rangable types" doesn't cut it, since there are different values/semantics.

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

4 participants