Slide 1

Slide 1 text

入門Go言語仕様輪読会 Untyped Constants @DQNEO 2021-04-15

Slide 2

Slide 2 text

自己紹介 ● @DQNEO (ドキュネオ) ● Goコンパイラ babygo の作者 ○ https://github.com/DQNEO/babygo ● 公式Goコンパイラ、言語仕様書コントリビュート歴有り

Slide 3

Slide 3 text

問題: 次の値の型は何でしょうか? 123 "hello" true

Slide 4

Slide 4 text

答え: なし 123 "hello" true ← 型なし ← 型なし ← 型なし

Slide 5

Slide 5 text

問題: 次の2文は何が違うでしょうか? const x = 123 var x = 123 注: const / var 違いの他に

Slide 6

Slide 6 text

答え: 型が違う const x = 123 var x = 123 var x int = 123 両辺とも型なし 両辺とも int =

Slide 7

Slide 7 text

型なし?

Slide 8

Slide 8 text

Go言語の定数は ● 型あり ● 型なし のどちらか

Slide 9

Slide 9 text

これらは全部型なし定数 ● 123 ● 1.1 ● "hello" ● ‘a’ ● true ● 1.0+3.0i

Slide 10

Slide 10 text

型なし定数を作ることも可能 const THREE = 3 const HELLO = "hello" 左辺で型を省き、右辺で型なし定数を使う

Slide 11

Slide 11 text

型なし定数のおもしろ性質(1) _人人人人人人_ > 型がない <  ̄Y^Y^Y^Y^Y^Y^ ̄

Slide 12

Slide 12 text

型がないのでユーザ定義型に代入可能 type MyBool bool var b MyBool = true もし true が bool 型だったら、代入できないはず (代入可能性の解説はこちら ) https://play.golang.org/p/63VHrn7XQVY

Slide 13

Slide 13 text

const HELLO = "hello" type MyString string var s MyString = HELLO もし HELLO が string型だったら、代入できない 型がないのでユーザ定義型に代入可能 (代入可能性の解説はこちら )

Slide 14

Slide 14 text

型がないのでいろんな型に代入可能 var y float32 = 97 var x int64 = 'a' var z byte = 97.0 (※ ただし “representable” な場合に限る) どれも 右辺は 「左辺の型の97」扱い

Slide 15

Slide 15 text

型なし定数のおもしろ性質(2) 「型を隠し持っている」

Slide 16

Slide 16 text

型なし定数にも種類がある リテラル 種類 1 integer constant 1.0 floating-point constant 'a' rune constant "hello" string constant true boolean constant

Slide 17

Slide 17 text

種類に応じて default type がある リテラル 種類 default type 1 integer constant int 1.0 floating-point constant float64 'a' rune constant rune(=int32) "hello" string constant string true boolean constant bool

Slide 18

Slide 18 text

var x = 1.0 型が必要です。 あなたの型を教えてください float64 です 聞かれたときだけ答える default type とは、 「型を要求されたとき」に使われる型

Slide 19

Slide 19 text

型を要求される文脈の例 ● var x = 123 ● y := 1.0 ● var ifc interface{} = 1.0 ● fmt.Printf("%v", 1.0)

Slide 20

Slide 20 text

● var x uint8 = 1.0 私は uint8型です。 私に従ってください わかりました default typeは、必ずしも使われるわけでは ない uint8として振る舞う default typeは使われない

Slide 21

Slide 21 text

型なし定数のおもしろ性質(3) 「すごい数もOK」

Slide 22

Slide 22 text

超巨大数を定義できる const HUGE = 92233720368547758070 ↑ int64の最大値より大きい

Slide 23

Slide 23 text

定義できるが表示できない const HUGE = 92233720368547758070 fmt.Println(HUGE) _人人人人人人_ > コンパイルエラー <  ̄Y^Y^Y^Y^Y^Y^ ̄ constant 92233720368547758070 overflows int64

Slide 24

Slide 24 text

int型変数に代入できない const HUGE = 92233720368547758070 var x = HUGE constant 92233720368547758070 overflows int64 _人人人人人人_ > コンパイルエラー <  ̄Y^Y^Y^Y^Y^Y^ ̄

Slide 25

Slide 25 text

Go言語氏 「default type があるとは言ったが、 default type に収まるとは言ってない」

Slide 26

Slide 26 text

float型変数には代入できる const HUGE = 92233720368547758070 var x float64 = HUGE fmt.Printf("%v\n", x) => 9.223372036854776e+19 精度は落ちる (当然)

Slide 27

Slide 27 text

巨大数同士の定数計算ができる const HUGE = 92233720368547758070 const X_HUGE = 922337203685477580700 var x uint8 = X_HUGE / HUGE 計算結果がuint8 に収まるのでOK => 10

Slide 28

Slide 28 text

超細かい小数を定義できる const ROOT2 = 1.41421356237309504880168872420969807856 967187537694807317667974 float64 の精度を超えている

Slide 29

Slide 29 text

二乗すると 2 になる const ROOT2 = 1.41421356237309504880168872420969807856 967187537694807317667974 fmt.Println(ROOT2 * ROOT2) // => 2 _人人人人人人_ > 精度高すぎ <  ̄Y^Y^Y^Y^Y^Y^ ̄

Slide 30

Slide 30 text

変数を経由すると精度が落ちる const ROOT2 = 1.41421356237309504880168872420969807856 967187537694807317667974 f := ROOT2 // ここで float64に詰め替えられる fmt.Println(f * f) // => 2.0000000000000004 https://play.golang.org/p/JMtw6IZjDtP

Slide 31

Slide 31 text

Goの言語思想 “they are just regular numbers” 型なし定数の数値は「ただの数」である const HUGE = 92233720368547758070 const ROOT2 = 1.4142135623730950488016887242096980785696718753769 4807317667974 https://blog.golang.org/constants

Slide 32

Slide 32 text

Goの言語思想 “they live in a kind of ideal space of values” 型なし定数は、型の制約のない自由な理想空間 で生きている

Slide 33

Slide 33 text

Goの言語思想 1 1.000 1e3-99.0*10-9 '\x01' ‘a’ (= ‘0x97 ’ 97) '\u0001' 'b' - 'a' 1.0+3i-3.0i これらはどれも 型なし定数 1 と同等に扱える

Slide 34

Slide 34 text

おまけ この辺は例外的な仕様 ● string(97) // => "a" ● string(97.0) // コンパイルエラー

Slide 35

Slide 35 text

ご清聴 ありがとうございました