type T interface{}
type foo struct { a T; }
type bar foo.duplicate(T=int)
type T interface{}
type foo struct { a T; }
var bar foo.assert(T=int)
> Runtime Boxing
>
> The most annoying thing about manual runtime boxing with interface{} is the
> loss of type-safety; for a simple collection class, the user must manually
> ensure that nothing of the wrong type accidentally gets added or deal with
> the resulting mess of type switches and assertions. But again, this is easy
> for the compiler to check if we don't approach it as generics per-say and
> just as a new language convenience. Again, the actual syntax and naming
> isn't worth bikeshedding, but for the sake of an example we could have a
> keyword "assert" such that one could write:
>>
>> type T interface{}
>> type foo struct { a T; }
>> var bar foo.assert(T=int)
>
> The extra ".assert(T=int)" would not change the compiled code at all, it
> would simply hint to the compiler that anywhere type T is used with respect
> to bar, it must be an int and not just a generic interface.
This is similar to the type erasure process that happens for example
in Java generics. Again, you have to think, in such a context, about
what the rules should be ?
Can you assign a foo<T=int> to a
foo<T=interface{}> ? How do you define a tree data structure in this
context ? Can you write a generic sort algorithm ?
Can you write a generic map function ? (something that takes a []T and
a "func(T) U" and returns a []U).
If you can't do these, what can you do with this proposal ?
> I'm sure that this approach has some flaws; constructive criticism is very
> welcome. Please don't discuss specific details/problems of the examples,
> they really are just examples to illustrate the broader point. Thoughts?
> Comments? Use cases this doesn't address?
I'm pretty sure you can find earlier discussions about these concepts.
I find it very difficult to imagine how the concepts above can be
turned into something usable (e.g. I can't imagine using them to solve
the questions I ask).
For the first example, mixing the concept of
interface with a variable type is very confusing.
type T interface{}
type foo struct { a T; }
type bar foo.duplicate(T=int)
type T interface{}
type foo struct { a T; }
type bar struct { a int; }The hint (whatever the final syntax) would specify to the compiler a base type (in this example foo) and a list of type substitutions (in this example T->int). The compiler would take a copy of the code from the base type, perform the appropriate substitutions, and insert the result in place of the "duplicate" hint. Compilation proceeds as normal, failing if the type substitution results in invalid code.
Can you explain how to define a tree structure in this setup?
Rémy.
type T interface{}
type foo struct { a T; }
var bar foo.assert(T=int)
type T interface{}
type foo struct { a T; }
var bar foo
Can you explain how to define a tree structure in this setup?
package fooNote that this is already valid Go code; the package author does not need to do anything to support generics in this model except use sane aliases for their interface{}. Then a user of the package could write:
type K interface{}
type V interface{}
type TreeNode struct {
Left, Right *TreeNode
Key K
Value V
}
import "foo"and the result would be an implementation of foo.TreeNode with the appropriate type substitutions.
type myNode foo.TreeNode.duplicate(K=int, V=string)
In the runtime-boxing case, the hint would not change the compiled output at all; compilingtype T interface{}would result in *exactly the same* binary (down to the very last bit) as compiling
type foo struct { a T; }
var bar foo.assert(T=int)type T interface{}
type foo struct { a T; }
var bar foo
I think providing a generic data structure without this ability
reduces its usability quite much.
Rémy.
I did a an experiment with annotation to generate specialized package based on the behavior you describe : https://github.com/champioj/geno ( I'm currently changing the annotation to be in the package comment section )It work surprisingly well except for one drawback : circular reference. I'm not sure if it's possible to hack around this problem...or if any change to the language would be needed to help this case.