-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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: Go 2: type assertion extensions, defined type assertions and generics #39716
Comments
Proposal 3, as currently stated, is inherently not backwards compatible. For example: package main
type CustomInt int
func Example(v interface{}) {
switch v.(type) {
case int:
println("built-in")
case CustomInt:
println("custom")
}
}
func main() {
Example(CustomInt(0))
} Currently, this will print |
In the new generics draft, interfaces can contain a list of valid underlying types. type Int interface {
type int, int8, int116, int32, int64, uint, uint8, uint16, uint32, uint64
} These can only be used as type parameters. A simpler proposal would be to allow using these in type assertions and type switches. x := v.(Int)
switch x := v.(type) {
case Int:
} However, I don't really see the value. |
@DeedleFake This doesn't seem to be the case, I think you may have misinterpreted. |
If that was true, then the example
If |
Proposal: type assertion extensions, defined type assertions and generics
Introduction
Currently, type assertions can be used on interface values to determine the dynamic type of a value:
Type switches borrow the type assertion syntax:
This document contains a set of 6 proposals to extend on this idea.
Proposal 1 - Allow multiple types in type assertions
Extend the type assertion syntax to allow multiple types, just as in the switch case statements:
This works just like in a type switch
case
: if val holds an int or float64 ok will be true and x will have a the dynamic type of float32 or float64.Proposal 2. Allow defined type assertions
A defined type assertion is declared using the new keyword
meta
:Because of the keyword
meta
a defined type assertion is also called a meta type. A defined type assertion or meta type can be used anywhere where an "inline" type assertion can be used.Like types, meta types are exported if starting with a capital character. Meta types can include other meta types:
Proposal 3. Extended type assertions to include type kinds
The
reflect
packages uses the concept of type kinds to identify types as kind of types such as functions, channels, etc. Type assertions are extended to support the same idea.The full list is illustrated using a type switching statement:
Meta types using type kinds may help to write more concise and clearer documentation and can be used to validate function arguments of type interface{}:
More intricate examples of using type kinds are given after generics have been discussed.
Proposal 4. Extend type assertions to include comparison operators
More intricate examples are given in the generic section.
Proposal 5. Generics can be based on meta types
A generic function is declared by using a meta type in its signature.
A generic type is defined by using a meta type in its definition.
A generic type may include a meta type signature directly after its name.
If the meta type signature is omitted it defaults to the order of appearance of the used meta types.
In general, the meta type signature will be omitted whenever possible because it is shorter and therefore more readable. A common case where the type signature is required is when a meta type is used only in non-exported struct fields, but the type self is exported. This is case for the
Bimap(K,V)
example above.Some less common cases where meta type signature is required are:
A common reason to include the meta signature although not required would be clarity, for example because a different meta type order is more natural.
If a meta signature is provided, all meta types must be listed. Partial lists are not allowed.
Generic struct types cannot be specialized for specific types such as for example in C++.
It is not necessary to repeat the meta type signature on generic type methods, but it may be done so for reason of clarity.
It is recommended that a package that exports generics types use one or two type meta types at most. They should be name with single capital letter like
T
,K
,V
etc. This would make than easily recognisable.An exception would be a
types
packages for example that definesInts
,Floats
, etc. These meta types could be used for both generics, type assertions and type switching.When using a generic type or or function, each meta type identifier must be bound to a concrete type. This process is called type binding.
In many case, type binding can be done automatically by the compiler using the context in which an generic type is used. In cases where this is not possible, or where the inferred binding is not desired, the binding must be given explicitly.
When instantiating a generic type, the types that are (automatically or implicitly) bound to the meta types are compile-time type asserted using the meta type by the compiler.
A meta type can only bind to a single concrete type.
When implementing generic functions, a compilation error occurs when an operation is attempted that is not supported by all types in the meta type.
Besides the common applications of generics, in Go generics can also be used to provide a type safe signature to functions that are otherwise implemented using reflection.
Proposal 6.
compile
blocks in generic functions compile different code depending on typeThis is best explained using an example.
Another example.
The text was updated successfully, but these errors were encountered: