こちらは Goクイズ Advent Calendar 2020 - Qiita の10日目の記事です。
問題
今回は、皆さん大好きなiotaの問題です。
package main import "fmt" const ( X = 0 A, B, C = iota, iota + 1, iota * 2 D, _, E _, F, _ G = iota + iota ) func main() { fmt.Println(D + E + F + G) }
さて、答えはどれでしょう?
- compile error
- 12
- 18
- 24
解答
https://play.golang.org/p/6c_X0VSSul4
正解
スクロールした先にあります!
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
正解は、3の 18
です。
解説
iotaについて考える時、気にしないといけない事はたった一つです。
それは、 iotaがConstDecl中の何番目のConstSpecに現れているか です。
用語を解説します。
ConstDecl, ConstSpecとは
ConstDeclは、次のような形式で行われる 定数宣言
です。
const ( A = 1 B = 2 C ) const D = 3 const E = 4 const F = 5
A~Cは、const
キーワードに始まり、 ()
で括られている、1つのConstDeclです。
D~Fは、 const
キーワードの書かれているそれぞれの行がConstDeclに該当します。
ConstSpecは、上記のコードで示される A = 1
D = 3
など、定数の識別子とその値を指定している部分に該当します。
C
もConstSpecに該当します。1つのConstDecl中で右辺を省略したConstSpecを書いた場合、直前のConstSpecの右辺をもう一度書いた事と同じと見なされます (この場合は = 2
を書いているのと同じなので、Cの値は 2
となります)。*1
iotaの正体について
今回のポイントは、 ()
付きのConstDeclは、複数のConstSpecを持つことができ、そのindexを内部的に保持している ことです。
そして、iotaの値は ConstDecl中でiotaが使われているConstSpecのindexの値 でしかありません。
これがiotaの正体です。
例を見てみましょう。
const ( A = iota // index: 0 B // index: 1 C // index: 2 )
ConstSpecのindexは0 originなので、この場合は A, B, C
が 0, 1, 2
となります。
const ( A = iota // index: 0 B = 0 // index: 1 C = iota // index: 2 )
この例では、Bでiotaを使っていませんが、気にすべきなのはConstSpecのindexのみなので C
は 2
となります。
const ( A, B = iota, iota // index: 0 C, D // index: 1 )
A, B
のConstSpec中で2回iotaが登場していますが、ConstSpecのindexは 0
なので、 A, B
はいずれも 0
となります。
C, D
についても同様に 1, 1
となります。
問題の解説
今回の問題を振り返ります。
const ( X = 0 // index: 0 A, B, C = iota, iota + 1, iota * 2 // index: 1 D, _, E // index: 2 _, F, _ // index: 3 G = iota + iota // index: 4 )
ConstSpecのindexを書いてしまえば、一気に内容が理解しやすくなります。
A, B, C
はConstSpecのindexが 1
なので、それぞれ 1
, 1 + 1 => 2
, 1 * 2 => 2
です。
D, E
は、右辺を = iota, iota + 1, iota * 2
と書いているのと同じと見なされるので、それぞれ 2
, 2 * 2 => 4
です。
F
も同様に、 3 + 1 => 4
です。
最後に、Gについてですが、これもiotaがConstSpecのindexでしかないことを考慮すると 4 + 4 => 8
となります。
結果、 D + E + F + G
は 2 + 4 + 4 + 8
で 18
となります。
言語仕様の該当箇所について
今回解説した内容は、
に書かれているので、時間のある時にぜひ読んでみてください。
*1:左辺側に現れる定数の型についても同様のルールが適用されますが、ここでは突っ込んで解説しません。