定数生成器 iota についてちゃんと書く

第16回『プログラミング言語Go』オンライン読書会」で出た話題を過去の失敗を含めて Zenn で書いたが,微妙に反応がある気がするので,今後の自分のためにも iota1 についてちゃんと書いておいたほうがいいかもしれない。

まずは用語から入るとしよう。

定数の中でも rune,整数(int など),浮動小数点数(float64 など),複素数(complex128 など)の定数をまとめて「数値定数(numeric constants)」と呼ぶ。 数値定数の定数式(constant expression)は以下のようにリテラルで表すことができる。

package main

import "fmt"

const (
    Rune         = 'a'
    Integer      = 1 << 2
    FloatingPont = 3.4
    Complex      = 5.6 + 7.8i
)

func main() {
    fmt.Println(Rune, Integer, FloatingPont, Complex) // 97 4 3.4 (5.6+7.8i)
}

(型付けなし定数(untyped constant)として宣言されている点に注意)

定数生成器(constant generatoriota は数値定数の中で事前に宣言された型付けなし整数を表す識別子で,以下の性質を持つ。

Within a constant declaration, the predeclared identifier iota represents successive untyped integer constants. Its value is the index of the respective ConstSpec in that constant declaration, starting at zero.

強調は私がやりました。 ポイントは iota は(const (...) 内の)インデックス値であってカウンタではないということだ。

私が過去にやらかした勘違いについて敢えて解説すると,もともと定数宣言は

Within a parenthesized const declaration list the expression list may be omitted from any but the first ConstSpec. Such an empty list is equivalent to the textual substitution of the first preceding non-empty expression list and its type if any. Omitting the list of expressions is therefore equivalent to repeating the previous list.

という性質があり,同じ定数式の繰り返しを省略することができる。

package main

import "fmt"

const (
    c1 = 1
    c2
    c3
)

func main() {
    fmt.Println(c1, c2, c3) // 1 1 1
}

これとインデックス値 iota を組み合わせて

package main

import "fmt"

const (
    c1 = 1 + iota
    c2
    c3
)

func main() {
    fmt.Println(c1, c2, c3) // 1 2 3
}

のように書けるのだが,この字面から何となく iota をカウンタと思い込んでいたのだった。 嗚呼,恥ずかしい…

上の定数宣言は以下と等価である。

const (
    c1 = 1 + iota // c1 == 1 (iota == 0)
    c2 = 1 + iota // c2 == 2 (iota == 1)
    c3 = 1 + iota // c3 == 3 (iota == 2)
)

また ConstSpec 単位のインデックス値なので,こんな変態的な記述もできる(笑)

const (
    bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0  (iota == 0)
    bit1, mask1                          // bit1 == 2, mask1 == 1  (iota == 1)
    _, _                                 //                        (iota == 2, unused)
    bit3, mask3                          // bit3 == 8, mask3 == 7  (iota == 3)
)

というわけで,どっとはらい。

参考図書

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)


  1. ちなみに iota は「イオタ」と読む。ギリシャ文字のイオタ(Ι / ι)を指す言葉である。 ↩︎