Upgrade to Pro — share decks privately, control downloads, hide ads and more …

入門Go言語仕様 / Go Specification Untyped Constants

7b606c5039f083d13e2d2320ce6ddcfa?s=47 DQNEO
April 15, 2021

入門Go言語仕様 / Go Specification Untyped Constants

7b606c5039f083d13e2d2320ce6ddcfa?s=128

DQNEO

April 15, 2021
Tweet

Transcript

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

  2. 自己紹介 • @DQNEO (ドキュネオ) • Goコンパイラ babygo の作者 ◦ https://github.com/DQNEO/babygo

    • 公式Goコンパイラ、言語仕様書コントリビュート歴有り
  3. 問題: 次の値の型は何でしょうか? 123 "hello" true

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

    型なし
  5. 問題: 次の2文は何が違うでしょうか? const x = 123 var x = 123

    注: const / var 違いの他に
  6. 答え: 型が違う const x = 123 var x = 123

    var x int = 123 両辺とも型なし 両辺とも int =
  7. 型なし?

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

  9. これらは全部型なし定数 • 123 • 1.1 • "hello" • ‘a’ •

    true • 1.0+3.0i
  10. 型なし定数を作ることも可能 const THREE = 3 const HELLO = "hello" 左辺で型を省き、右辺で型なし定数を使う

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

  12. 型がないのでユーザ定義型に代入可能 type MyBool bool var b MyBool = true もし

    true が bool 型だったら、代入できないはず (代入可能性の解説はこちら ) https://play.golang.org/p/63VHrn7XQVY
  13. const HELLO = "hello" type MyString string var s MyString

    = HELLO もし HELLO が string型だったら、代入できない 型がないのでユーザ定義型に代入可能 (代入可能性の解説はこちら )
  14. 型がないのでいろんな型に代入可能 var y float32 = 97 var x int64 =

    'a' var z byte = 97.0 (※ ただし “representable” な場合に限る) どれも 右辺は 「左辺の型の97」扱い
  15. 型なし定数のおもしろ性質(2) 「型を隠し持っている」

  16. 型なし定数にも種類がある リテラル 種類 1 integer constant 1.0 floating-point constant 'a'

    rune constant "hello" string constant true boolean constant
  17. 種類に応じて 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
  18. var x = 1.0 型が必要です。 あなたの型を教えてください float64 です 聞かれたときだけ答える default

    type とは、 「型を要求されたとき」に使われる型
  19. 型を要求される文脈の例 • var x = 123 • y := 1.0

    • var ifc interface{} = 1.0 • fmt.Printf("%v", 1.0)
  20. • var x uint8 = 1.0 私は uint8型です。 私に従ってください わかりました

    default typeは、必ずしも使われるわけでは ない uint8として振る舞う default typeは使われない
  21. 型なし定数のおもしろ性質(3) 「すごい数もOK」

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

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

    92233720368547758070 overflows int64
  24. int型変数に代入できない const HUGE = 92233720368547758070 var x = HUGE constant

    92233720368547758070 overflows int64 _人人人人人人_ > コンパイルエラー <  ̄Y^Y^Y^Y^Y^Y^ ̄
  25. Go言語氏 「default type があるとは言ったが、 default type に収まるとは言ってない」

  26. float型変数には代入できる const HUGE = 92233720368547758070 var x float64 = HUGE

    fmt.Printf("%v\n", x) => 9.223372036854776e+19 精度は落ちる (当然)
  27. 巨大数同士の定数計算ができる const HUGE = 92233720368547758070 const X_HUGE = 922337203685477580700 var

    x uint8 = X_HUGE / HUGE 計算結果がuint8 に収まるのでOK => 10
  28. 超細かい小数を定義できる const ROOT2 = 1.41421356237309504880168872420969807856 967187537694807317667974 float64 の精度を超えている

  29. 二乗すると 2 になる const ROOT2 = 1.41421356237309504880168872420969807856 967187537694807317667974 fmt.Println(ROOT2 *

    ROOT2) // => 2 _人人人人人人_ > 精度高すぎ <  ̄Y^Y^Y^Y^Y^Y^ ̄
  30. 変数を経由すると精度が落ちる const ROOT2 = 1.41421356237309504880168872420969807856 967187537694807317667974 f := ROOT2 //

    ここで float64に詰め替えられる fmt.Println(f * f) // => 2.0000000000000004 https://play.golang.org/p/JMtw6IZjDtP
  31. Goの言語思想 “they are just regular numbers” 型なし定数の数値は「ただの数」である const HUGE =

    92233720368547758070 const ROOT2 = 1.4142135623730950488016887242096980785696718753769 4807317667974 https://blog.golang.org/constants
  32. Goの言語思想 “they live in a kind of ideal space of

    values” 型なし定数は、型の制約のない自由な理想空間 で生きている
  33. Goの言語思想 1 1.000 1e3-99.0*10-9 '\x01' ‘a’ (= ‘0x97 ’ 97)

    '\u0001' 'b' - 'a' 1.0+3i-3.0i これらはどれも 型なし定数 1 と同等に扱える
  34. おまけ この辺は例外的な仕様 • string(97) // => "a" • string(97.0) //

    コンパイルエラー
  35. ご清聴 ありがとうございました