Go のジェネリクス調査
2023-07-14 Tetsuya Morimoto
概要
Go に足りないと散々言われ続けたもの
ジェネリクスとは
ジェネリクス (Generics) とは
public class Stack<T> {
private LinkedList<T> stack;
public Stack() {
stack = new LinkedList<>();
}
public void push(T item) {
stack.addFirst(item);
}
public T pop() {
if (isEmpty()) {
return null;
}
return stack.removeFirst();
}
public int size() {
return stack.size();
}
}
Java で書いた�パラメーター多相のコード例
ジェネリクスはなにが嬉しいの?
一般論はインターネットをググって調べて、ここではもりもとの経験から
メリット
デメリット
現代のプログラミング�の設計は分割統治
ジェネリクスでよく聞くコメント
ジェネリクスのジレンマ
The Generic Dilemma Posted on Thursday, December 3, 2009. Go 言語の開発チームの Russ Cox 氏のブログから引用
C 言語の方法
C++ 言語の方法
Java の方法
Go の開発者はジェネリクスに関心がないとか、
Go の開発者はジェネリクス知らないとか (ひどい) 、
2009年から検討していてそんなことはない
Go におけるジェネリクスの提案
10年以上の検討の歴史
Go におけるジェネリクス
List<? extends Number>
List<? super Number>
詳細は記事を読んで
Go 1.18/1.20 Generics
(Go 1.18) 導入された概念
この4つの概念を詳細にみていく
func SumNumbers[K comparable, V Number](m map[K]V) V
型パラメーター
SumNumbers[string, int64](ints)
SumNumbers[string, float64](floats)
型引数
制約
type Number interface {
int64 | float64
}
型セット
ジェネリクスのチュートリアルをやってみよう
インターフェースのセマンティクスの変更
type any = interface{}
type Reader interface {
Read([]byte) (int, error)
}
type myType interface {
~int | ~string
io.Writer
}
型パラメーターへの制約
(Go 1.20) 組み込みの制約
(Go 1.20) 型の制約を満たすルール�
T implements C; or
C can be written in the form interface{ comparable; E },
where E is a basic interface� and T is comparable and implements E.
型セット (Type sets)
インターフェースの定義
InterfaceType = "interface" "{" { InterfaceElem ";" } "}" .
InterfaceElem = MethodElem | TypeElem .
MethodElem = MethodName Signature .
MethodName = identifier .
TypeElem = TypeTerm { "|" TypeTerm } .
TypeTerm = Type | UnderlyingType .
UnderlyingType = "~" Type .
Underlying Type (1)
>>> inspect.getmro(int)
(<class 'int'>, <class 'object'>)
Underlying Type (2)
Underlying Type (3)
Hierarchy is too stringent:� Types in large programs do not easily fall into hierarchies.� Programmers spend too much time� deciding tree structure and rearranging inheritance.
Reduce typing.� Keep the type system clear. No type hierarchy.� Too clumsy to write code by constructing type hierarchies.� It can still be object-oriented.
ジェネリクスがうまくいくパターン (1)
When To Use Generics by Ian Lance Taylor から引用
型パラメーターはいつ使うか?
シンプルなガイド
ジェネリクスがうまくいくパターン (2)
When To Use Generics by Ian Lance Taylor から引用
型パラメーターを使うべきではないとき
func ReadSome(r io.Reader) ([]byte, error)
↓ ↓
func ReadSome[T io.Reader](r T) ([]byte, error)
セマンティクスはほぼ同じだが、�デメリットしかない (1.18 時点)
(注意) 1.20 で comparable� が事情を変えた!
まとめ
まとめ
リファレンス
リファレンス
雑談