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

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

DQNEO
April 15, 2021

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

DQNEO

April 15, 2021
Tweet

More Decks by DQNEO

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  7. 型なし?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide