Edited at

Go2のジェネリクスがこうなったらいいのにという妄想を書く

https://qiita.com/lufia/items/242d25e8c93d88e22a2e

https://docs.google.com/document/d/1oCcqj9oRQepgIZi03SmcepwG-E9cUy372FOGo12jYVM/edit

上記を読んだ感想と妄想を書きます。


ジェネリクスはinterfaceを進化させる方向で進んでほしい。

上記を読むとジェネリクスはinterfaceとは完全に独立した存在のようです。

でも、それってGoのシンプルさを殺していないかなーって思います。

だってwhileとか削ってforだけにしたりclassを作らずに済ませたりとかそういう言語仕様に痺れたんですもの。


本当に欲しいもの

一番の問題はinterface{}を使わなくてはいけない状況であり、それを使わない選択肢がほしいだけなんです。


提案


演算子もinterfaceに


+の場合

interface Adder {

func Operator+(a Adder) Adder //Operator+を満たしていれば +が利用可能に
}

そして組み込み型は上記interfaceを満たしているものとします。

var a Adder = 1

b:= a+1

もちろん自作型もAdderを実装すれば加算可能になります。

他の演算子についてもinterfaceが組み込みで定義されていて、組み込み型はそれらを満たすみたいな感じにします。

そうすると自作型も演算子が使えるようになって幸せになりそうです。


interface 合成を可能に

TypeScriptをヒントにしていますが

直和型や直積型を定義できるようにします。


type interface InterfaceA {
InterfaceAMethod()
}
type interface InterfaceB {
InterfaceBMethod()
}

type InterfaceAandB = InterfaceA & InterfaceB // 直積型 埋込み型のシンタックスシュガー
type InteefaceAorB = InterfaceA | InterfaceB // 直和型

func ABTest(ab1 InterfaceAandB, ab2 InterfaceAorB) {
if a, ok :=ab1.(InterfaceA); ok {
if b, ok := a.(InterfaceB); ok {
// 絶対ここに来れる。
}
}

ab2.InterfaceAMethod() // まだab2のinterfaceは確定していないのでコンパイルエラーになる
switch ab2.(type) {
case InterfaceA:
ab2.InterfaceAMethod() // ok
default:
// interfaceBがかならず来る
ab2.InterfaceBMethod() // ok
}
}

こんな感じです。


プロパティのサポート

これは必要ないかもですがあったら幸せです。


interface GetterA {
Get A() SomeInterface // a:= getterA.A のシンタックスシュガー
}

interface SetterA {
Set A(a SomeInterface) // setterA.A = xxx のシンタックスシュガー
}


まとめ

ただの妄想を書いてみました。

ジェネリクスの代わりになるかはわかんないですが、これが自分にとっての本当に欲しいものな気がします。