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: core/generics: allow slices/arrays of not initialized constraints #50758

Closed
GGCristo opened this issue Jan 22, 2022 · 4 comments
Closed

Comments

@GGCristo
Copy link

GGCristo commented Jan 22, 2022

With the actual implementation, if we want to create a function that receive a generic slice, we would write something like this:

func fooFunc[T any](s []T) {}

A generic slice with more types:

type basicPrimitiver interface {
 int | float64
}
type foo[T basicPrimitiver] interface {
 []T | string
}

func test[U basicPrimitiver, T foo1[U]] (s T) {
	fmt.Println(len(s))
}

func main() {
	test[int]([]int{1, 2, 3})
	test[int]("hello") // <- I need to write an unrelated "int" or "float64", which in my opinion is not a very readable code
}

I think this situation could be improved.
One way is to allow not initialized constraints with slices and arrays.

// ...
type foo interface {
 []basicPrimitiver | string
}
// ...

If I have understood (https://go.dev/doc/faq#convert_slice_of_interface) correctly, in case someone tries to use the interface like a regular interface instead of a constraint for generics, the compilation will fail

type foo interface {
 []interface{} // []any
}
func test1(p foo) { }
func test2[T foo](p T) { }

func main() {
 test2([]int{1,2,3}) // it works
 test2([]any{1,2,3}) // still works
 test1([]int{1,2,3}) // cannot use []int{…} (value of type []int) as type []interface{} ...
}

Maybe another less aggressive solution would be to have smarter type inference for these cases, so in the first example ...

test("hello")

... would be enough.

@gopherbot gopherbot added this to the Proposal milestone Jan 22, 2022
@ianlancetaylor
Copy link
Member

I'm sorry, I don't understand what you are proposing. Where is basicPrimitiver defined? What do you mean by "not initialized constraints"? What problem are you trying to solve?

@DeedleFake
Copy link

DeedleFake commented Jan 23, 2022

If I understand correctly, what you want is the ability to define a constraint that's indexable, but you don't care what the underlying type is, correct? You can already do that:

type Indexable[T any] interface {
  []T | string
}

func Len[T Indexable[E], E any](v T) int {
  return len(v)
}

There's no way to specify an array regardless of length at the moment, unfortunately, but this'll cover slices and strings.

Edit: Hold on. I think that I just realized what you're asking for. You want to be able to use a constraint directly as an element type, correct? So you want to be able to do

type Indexable interface {
  []any | string
}

func Len[T Indexable](v T) int {
  return len(v)
}

Is that right? That's not going to work. With that syntax, there's no way for the compiler to know if you want a literal slice of interface{} or a slice where the elements satisfy interface{}.

@GGCristo
Copy link
Author

GGCristo commented Jan 23, 2022

I see, that makes sense. I tough that a slice where the elements satisfy interface{} was going to work in all cases, that is why I wrote something like this.

test2([]int{1,2,3}) // it works
test2([]any{1,2,3}) // still works

But did not realize that maybe someone wants his type to be literally of type "[]interface{}" which is completely valid.

I still don't feel this is right or readable code.

type basicPrimitiver interface {
 int | float64
}
type foo[T basicPrimitiver] interface {
 []T | string
}
// ...
test[int]("hello")
// or
test[float64]("hello")

You are practically writing random types, so the type inference don't bother you.

Possibly the type inference should check that if it can't determinate the type, it will try to check if it satisfies the rest of the types.

This issue may be changed from "Proposal" to "Questions"
Edit: Ok this is not the right place for questions (https://github.com/golang/go/wiki/Questions)
Then I close, and I ask somewhere else. Thanks

@GGCristo
Copy link
Author

Although

type foo interface {
    any
}

So this is an inconsistency.
In this case the compiler use any as a constraint not a literal if the user want a literal []interface{} or interface{}, they could use regular interfaces not generics.

@golang golang locked and limited conversation to collaborators Jan 23, 2023
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

4 participants