<p>There's an explosion of demands for generics in this sub, so why not make a thread tossing around some pseudocode?</p>
<p>Post some short pseudocode with a description.</p>
<p>I'll go first:</p>
<pre><code>package hashmap
type key interface {
Hash() uint64
}
type val interface{}
type HashMap struct {
ar []*node
}
type node struct {
k key
v val
next *node
}
func <key, val> New() HashMap {
return HashMap{
ar: make([]key, 256),
}
}
func (m *HashMap) Put(k key, v val) {
n := m.ar[k.Hash() % len(m.ar)]
for n != nil {
if n.val == v {
return
}
n = n.next
}
n = &node{
k: k,
v: v,
}
}
func (m *HashMap) Get(k key) (ret val) {
h := k.Hash()
n := m.ar[h % len(m.ar)]
for n != nil {
if n.k.Hash() == h {
ret = n.v
}
}
return
}
type String string
func (s String) Hash() (ret uint) {
for i := s {
ret += uint(s) << 1
}
return
}
//////////////
package main
import "foo/bar/hashmap"
func main() {
m := hashmap<hashmap.String, int>.New()
m.Put(hashmap.String("foo"), 1)
m.Put(hashmap.String("bar"), 2)
m.Put(hashmap.String("ham"), "eggs") // Compiler error. String does not match int type on val interface.
fmt.Println(m.Get(hashmap.String("foo"))) // 1
fmt.Println(m.Get(hashmap.String("bar"))) // 2
fmt.Println(m.Get(hashmap.String("ham"))) // 0
var foo string = m.Get(hashmap.String("foo")) // Compiler error. String does not match int type on val interface.
}
</code></pre>
<ul>
<li>Template parameters are put on functions only.</li>
<li>Template parameters must be interface types.</li>
<li>When calling a method, the template parameters are placed on the package.</li>
<li>When calling a method with template parameters, the compiler will throw an error if the types on the parameters or assignments from return types don't match.</li>
<li>When calling a method that accepts template parameters, but are not specified by the callee, the compiler will fall back to the interfaces declared in the method signature.</li>
<li>The go vet tool should report undeclared templates.</li>
</ul>
<p>Pro's:</p>
<ul>
<li>Generics are just interfaces. It makes it no different from what we've been working with for the 10+ years Go has been out.</li>
</ul>
<p>Con's:</p>
<ul>
<li>Not sure yet.</li>
</ul>
<p>Unknowns:</p>
<ul>
<li>The amount of compiler work involved.</li>
</ul>
<hr/>**评论:**<br/><br/>vAltyR47: <pre><p>Ian Lance Taylor's proposal on <a href="https://github.com/golang/proposal/blob/master/design/15292/2013-12-type-params.md" rel="nofollow">type parameters</a> is closest to how I see generics happening in Go. The limitations of the current proposal are discussed at the end, so I suggest giving it a read.</p></pre>iroflmaowtf: <pre><p>well... that's one thing that shouldn't be standardized</p></pre>dlsniper: <pre><p>Nobody asked for how to implement generics. Assume that the Go team can handle this. They explicitly said they need use-cases for where generics are needed, would improve the quality of life and so on. Let them handle the design of the feature and you make sure you send your use case where generics would be better than any other solution. Nobody needs yet another spurious thread about how someone who doesn't understand the complexity of the problem would solve it. No, we need to understand what's the problem first, the solve it. That's how good engineering is done and that's how the language we have today was born. So please, stop with this nonsense. </p></pre>iroflmaowtf: <pre><p>I, for one, would be very happy with being able to write this</p>
<pre><code>template <A, B, R>
func sum(a A, b B) R {
return R(a + b);
}
</code></pre>
<p>or this</p>
<pre><code>template <T>
func max(a T, b T) T {
if a > b {
return a
}
return b;
}
</code></pre>
<p>I think this would be a very low hanging fruit and would save a lot of copy-paste</p></pre>DeedleFake: <pre><p>Sure, why not. Here's a partial syntax I put almost no thought into, thus guaranteeing that it's better than any of Ian Lance Taylor's extremely long and well thought out proposals:</p>
<pre><code>type T generic {
oper T + T -> T
// Could also be things like:
// oper append([]T, T...) -> []T
// func (T) Less(T) bool
}
func sum(args ...T) (s T) {
for _, a := range args {
s += a
}
return s
}
</code></pre></pre>TheMerovius: <pre><p>You made my day :)</p></pre>champioj: <pre><p>I really like the idea of templated package.</p>
<p>I would just use them differently. Instead of specialize them inline, I would specialize them in the import section like this </p>
<pre><code>import "foo/bar/hashmap"<hashmap.String, int>
</code></pre>
<p>(actually I would prefer this syntax : </p>
<pre><code>import "foo/bar/hashmap" {key: hashmap.String, val: int}
</code></pre>
<p>, but that's bikeshedding)</p>
<p>Note that's is possible to have multiple specialization like this : </p>
<pre><code>import mapStrI "foo/bar/hashmap" {key: hashmap.String, val: int}
</code></pre>
<p>P.S. I'm not a native speaker. I feel my usage of the word specialize is very odd, I am using it correctly?</p></pre>randonymous: <pre><p>[you probably want '<a href="https://en.wiktionary.org/wiki/specify" rel="nofollow">specify</a>' instead of 'specialize']</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传