先日のgolang.tokyoではswitch文に関するDevquizが出題された。
私はわかっていたつもりで乾杯の挨拶中に解説を話したが、間違えた解説だったので改めて仕様を確認した。
TL;DR
- 先日のgolang.tokyoのDevquizの解説で誤った解説をしてしまった
- https://golangtokyo.connpass.com/event/151926/
- Devquizは
switch ok := false; {...}というswitch文の挙動について
- Goの
switch文は条件以外に、switch内にスコープを絞ったStatementを書くことができる。switch x := f(); x { ... }
- Goの
switch文は条件(タグ)なしで書くことができる- タグなし
switch(tagless-switch)はswitch true
- タグなし
正しい答えは @makki_dさんに会場でも指摘してもらった。
クイズのswitch文、ok:=falseの後のセミコロンの後が空なのが味噌だよね#golangtokyo
— MakKi (@makki_d) November 5, 2019
golang.tokyo #27のDevquiz
2019/11/05に行われたgolang.tokyoの抽選では以下のDevquizが出題された。
// 以下のコードを実行すると何が出力されるか答えよ。
package main
import "fmt"
func main() {
switch ok := false; {
case true:
fmt.Println("true", ok)
case false:
fmt.Println("false", ok)
default:
fmt.Println("default")
}
}
何が出力されるかというと、true falseが出力される。
私はこれを「case trueが常に真として評価されるからtrue falseが出力される。」と解説したがそれは誤りだった。
switch文の言語仕様について
switch文の言語仕様は以下で確認することができる。
- Switch statements | The Go Programming Language Specification
Devquizのswitch文はtype switchではないので、ExprSwitchStmtとなる。
SwitchStmt = ExprSwitchStmt | TypeSwitchStmt .
ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
switch内にスコープを絞ったStatementを書ける
ExprSwitchStmtの定義を見ればわかる通り、switch文は実際にswitch文で評価したい式(Expression)と別に代入などの文(SimpleStmt)を含むことができる。
Devquiz中のswitch文もSimpleStmtとして、代入式を含んでいた
switch ok := false; {
Goのswitch文は式(タグ)なしで書くことができる
わかる人はもうわかっただろうが、Devquizのswitch文には式が含まれていない。これはGoの文法的に間違いではない。
There can be at most one default case and it may appear anywhere in the “switch” statement. A missing switch expression is equivalent to the boolean value true.
式が含まれていないswitch文はswitch trueとして条件評価が行われる。
よって、 今回のDevquizは「switch trueというswitch文だったので、case true:という条件が真になっていた」のが正しい解説となる。
switch ok := false; ok {と書けばok変数の値と各caseの値が比較され、(人間がパット見考える)期待どおりの挙動となる。
なお、switch {...}のような、式がないswitch文のことを、“タグなしswitch"(tagless-switch)と呼ぶ。
タグなしswitchの評価がswitch trueになることはプログラミング言語Goでもしっかり明記されている。
終わりに
2,3か月に1回くらいの割合でGoの言語仕様を読んでいる気がする。
Goの言語仕様は
この1ページだけだし、文中のキーワードにはリンクが付いているので勉強しやすい。
毎回忘れてやり直している気がするが、ExpressionとStatementの違いも頭に入ってきた。