-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
spec: add generic programming using type parameters #43651
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
an I'm also having trouble thinking how you could implement any |
This comment has been minimized.
This comment has been minimized.
I remain concerned that this proposal overloads words (and keywords!) that formerly had very clear meanings — specifically the words type and interface and their corresponding keywords — such that they each now refer to two mostly-distinct concepts that really ought to instead have their own names. (I wrote up this concern in much more detail last summer, at https://github.com/bcmills/go2go/blob/master/typelist.md.) Specifically, the word type today is defined as:
Under this proposal, I believe that a type would instead be either a set of values with operations, or a set of sets of values, each with its own set of operations. And today the word interface, in the context of Go, refers to a type, such that:
Under this proposal, a variable of interface type can store a value of any type with a method set that is any superset of the interface, unless that interface type refers to a set of sets of values, in which case no such variable can be declared. I'd like to see more detail on the exact wording proposed for the spec, but for now I am against this specific design, on the grounds that the ad-hoc overloading of terms is both confusing, and avoidable with relatively small changes in syntax and specification. |
func foo[T Stringer](t T) string {
return t.String()
}
func foo(t Stringer) string {
return t.String()
} The difference are very subtil. How will you document the best practice when a Go1 interface is enough ? |
I think interface{} is a mistake. It is a hack to permit something like void * without any semantic cues to help a user understand what is going on. I would have preferred to have "any" as a type in the language from the beginning, even it it was just an alias for interface{} under the covers. Of course, the new "any" is different than interface{}. It would be nice to have a named type that means "any type by reference" instead of "any type by substitution". |
Valid point, in your example, an interface would be the better choice. However, a more apt use case of generics would be |
What are the plans for amending the standard library to utilize generics? I see two important tracts of work here.
|
That sentence describes a struct. An interface is also a kind of type in Go, and it does not determine the set of values or operations that are present, only the set of methods. The fact that a type is not just a struct is why the syntax in the language is A generic type is just as concretely a set of values, operations, and methods as an interface is (which is to say, you an argue that it isn't). So either we should redefine interface to not be a type (by the definition you're quoting), or we should accept that a generic type is also a type, just one that requires type parameters to be resolved before it becomes a concrete type. If the proposal is misusing the term "type" in place of "type parameter" anywhere, I think that could be valid criticism... but it sounds like you're criticizing some ambiguous/arguably wrong terminology that exists in the Go language spec, which is terminology that is refuted by the language itself, as demonstrated by Go syntax above. If an interface is not a type, we should not prefix the declaration with the word That whole area of discussion seems off topic here, and clarifications to the existing language spec could be proposed somewhere else? I've read through the generic proposal several times and I haven't come away feeling like the terminology used was ambiguous or confusing, and your statements here do not effectively make the case for that either, in my opinion. |
The new "any" is not different from interface{} as a type constraint. |
Yes, and after generics are implemented, I hope the container package will be expanded to include other common data structures present in c++/java std libs |
The interface type definition specifies the methods (which are operations) present on values of that interface type. Because values must implement the interface to be used as that interface type, the interface type does indeed determine a set of values (always a superset of other types'). |
I'd expect a linter warning: "useless use of type parameter" |
If you want to go down that route... the same exact thing applies to the "overloading" of "type" to refer to generic types as well. In order for a value to be substituted for a type parameter, it must implement the interface constraints, and to do that, it must be a concrete type. Therefore, a generic type "does indeed determine a set of values (always a superset of other types)". It's the same thing. Either an interface is a type (in which case, it's fine for the proposal to use its current terminology), or it's not (in which case it's not okay for the Go language to define interfaces as types). Either way, someone could propose that the Go language spec is written in a confusing way in the quoted section, but it wouldn't change any outcomes regarding this proposal or the current-day reality of Go. |
This comment has been minimized.
This comment has been minimized.
In general, methods in Go are tied to type definitions and behave, in a lot circumstances, like any other function except that there's an argument placed before the function name. That's why, unlike most languages, Go allows you to call a method on a Interfaces are a strange exception to this. Despite the fact that a type is defined, as in |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@p-kraszewski The most up-to-date development is happening on the |
I think that you're confusing the declaration of a type parameter and the usage. The parameters are declared in function and type declarations and are essentially scoped to those functions and types. For contrived example, // declaration usages
// v v v
func Send[T any](c chan T, v T) {
c <- v
} Once they're declared, there basically isn't any difference in terms of usage between the type parameters and any other type, so they can be used as the element type of a channel, or the element type of a slice, or an argument to a function, or basically anything else. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
govet or golint could help with that. |
@fzipp That wouldn't be entirely accurate as a warning. Depending on the compiler's devirtualization pass, the two would have different performance characteristics. Assuming the "stenciling" approach for implementing generics, each version of |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Change https://golang.org/cl/291990 mentions this issue: |
For #43651 Change-Id: Idb511f4c759d9a77de289938c19c2c1d4a542a17 Reviewed-on: https://go-review.googlesource.com/c/go/+/291990 Trust: Ian Lance Taylor <iant@golang.org> Reviewed-by: Rob Pike <r@golang.org>
@fzipp Thanks, done (for the 1.16 release which should be out quite soon). |
Change https://golang.org/cl/292290 mentions this issue: |
Ported CL 291990 to this repo. For golang/go#43651. Change-Id: I3680b32ef7a53b3901e54d4d1dbf680231870490 Reviewed-on: https://go-review.googlesource.com/c/website/+/292290 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
To build a function for currying functions, etc. Does anyone know if you can match the parameter types of functions passed in as parameters in this proposal? Small changes to the syntax above for adding that and variable number of types: func Curry[func[ParamTs ...any], Ts ...any] (funcToCurry[ParamTs ...any] (...ParamTs), args ...Ts) {
// body of function
} Writing the above just makes me miss lisp/haskell honestly. I didn't even try doing the return type |
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
In #43651 (comment) I wrote
That is our usual way of using issues, but this issue continues to gather comments that are not relevant to tracking the work of implementing the proposal. Honestly, that was probably inevitable and understandable. But it's no longer the place for comments and questions about the proposal itself. I'm going to lock this issue and close it. We won't forget about the implementation without a tracking issue, I promise. |
Change https://golang.org/cl/303389 mentions this issue: |
Change https://golang.org/cl/306689 mentions this issue: |
Change https://golang.org/cl/343732 mentions this issue: |
We propose adding support for type parameters to Go. This will change the Go language to support a form of generic programming.
A detailed proposal document has been published, with input from many members of the Go community. We are now taking the next step and proposing that this document become a part of the language.
A very high level overview of the proposed changes:
func F[T any](p T) { ... }
.type MySlice[T any] []T
.func F[T Constraint](p T) { ... }
.any
is a type constraint that permits any type.For more background on this proposal, see the recent blog post.
In the discussion on this issue, we invite substantive criticisms and comments, but please try to avoid repeating earlier comments, and please try to avoid simple plus-one and minus-one comments. Instead, add thumbs-up/thumbs-down emoji reactions to comments with which you agree or disagree, or to the proposal as a whole.
If you don't understand parts of the design please consider asking questions in a forum, rather than on this issue, to keep the discussion here more focused. See https://golang.org/wiki/Questions.
The text was updated successfully, but these errors were encountered: