次期 Go 言語で導入される総称型について予習する(その2)

【2021-02-21 追記】 型パラメータの提案(「総称型」というのは厳密には正しくないらしい)は2021年2月に承認され,製造フェーズに入ったようだ。
  1. 次期 Go 言語で導入される(かもしれない)総称型について予習する
  2. 次期 Go 言語で導入される総称型について予習する(その2) ←イマココ
  3. 次期 Go 言語で導入される総称型について予習する(その3)

以前書いた記事に関して,仕様が変わったらしい。

そこで,これまでのおさらいと変更点について簡単に紹介する。

「総称型」のおさらい

次期 Go 言語で導入される「総称型(generics)」について,これまで提案されていた仕様は以下の通り。

contract ordered(t T) {
    t < t
}

func Max(type T ordered)(x, y T) T {
    if x < y {
        return y
    }
    return x
}

Max() 関数の (type T ordered) の部分が「型パラメータ(type parameter)」で,これによって型 T が総称型であることを示す。 また ordered は「型コントラクト(type contract)」と呼ばれ,総称型に対する制約(constraint)として機能している。

制約の定義

新しい提案では,型コントラクトを捨て,制約の定義を以下のように変更する。

type ordered interface {
	type int, int8, int16, int32, int64,
		uint, uint8, uint16, uint32, uint64, uintptr,
		float32, float64,
		string
}

func Max(type T ordered)(x, y T) T {
    if x < y {
        return y
    }
    return x
}

以前の型コントラクトとの違いは 既存のキーワードがそのまま使える ことである。 文法も interface 型の宣言とほぼ同じだが type int, int8, ... といった感じに型の列挙ができる点がこれまでと異なる。

これにより,制約 ordered を満たす型であれば

func main() {
	fmt.Println(Max(Max(1, 2), 3))               //Output: 3
    fmt.Printf("%#U\n", Max(Max('あ', 'い'), 0)) //Output: U+3044 'い'
}

などと記述できる。

なお,これまでの interface 型も制約として使える。 たとえば,こんな感じ。

func SayError(type E error)(e E) string {
	return e.Error()
}

func main() {
	fmt.Println(SayError(io.EOF)) //Output: EOF
}

更に interface 型を入れ子にすることで複雑な制約条件を構成することもできる。

注入するか単態化するか

ところで先程の

func SayError(type E error)(e E) string {
	return e.Error()
}

は,わざわざ総称型を使わなくとも今までの書き方で

func SayError(e error) string {
	return e.Error()
}

としても見た目の結果は同じになる。

しかし,今までの書き方が実行時に動的ディスパッチを行う「依存の注入(depencency injection)」であるのに対し,総称型を使った記述はコンパイル時に型ごとに別々の関数として展開される。 これを「単態化(monomorphization)」と呼ぶ。

依存の注入と単態化ではリソース管理の戦略がまるで異なる。

たとえば上述の SayError() 関数を総称型で記述するのは,どう考えても効率が悪い。 error に包摂される型は必要に応じていくらでも定義可能であり,それらの型ごとに単態化されるなどぞんぞがさばる。

逆に Max() 関数なんかは,基本型の振る舞いを interface で括るのが難しいこともあり,コストの高い float64 型の math.Max() くらいしか標準では実装されてなかったりする。 こういったものを総称型で記述できるようになれば(OAOO 原則の観点から考えても)コード管理しやすくなるだろう。

Go プログラマは息をするように依存を注入する」。 他のプログラミング言語が総称型で書いているかなりの部分を依存の注入で簡単に纏めてしまえるのが Go 言語の強みであるが,使える道具は多いに越したことはない。

Go 2 Playground

次期 Go 言語用に新しい Playground が公開されている。

総称型についてもここで色々と試せるようなので,遊びに行ってみてはいかがだろうか。

早ければ Go 1.17 でお披露目?

だいぶ仕様が固まってきた総称型であるが,早ければ2021年8月にリリース予定の Go 1.17 でお披露目されるかもしれないとのこと。

たのしみ!

ブックマーク

参考図書

photo
プログラミング言語Go
アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)
丸善出版 2016-06-20 (Release 2021-07-13)
Kindle版
B099928SJD (ASIN)
評価     

Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想はこちら

reviewed by Spiegel on 2021-05-22 (powered by PA-APIv5)