2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
Zigはうっかりコーディングミスを絶対に許さない!(全1記事)
リンクをコピー
記事をブックマーク
小林哲之氏(以下、小林):それでは、始めます。tetsu_kobaと申します。今日はZigの話をしたいと思います。
Zig言語は、けっこう新しい言語なので、初めて聞く方も多いかと思います。「5分でざっと理解するZig言語」というページを作っておいたので、こちらをご覧になってください。
ところでみなさん、解決まで何時間もかかったバグの原因が、実は数秒で直せるような、しょうもないうっかりコーディングミスだったという経験はありませんか? 私は何度もあります。
バグの原因が、しょうもないうっかりコーディングミスだったということを嫁に話しました。途端に泣き崩れる嫁。「俺はうっかりコーディングミスを絶対に許さない! 絶対にだ!」
というふうにZigの作者は思ったのかどうかわかりませんが、Zig言語は、「Cであったいろいろな問題をとにかく解決する」ということを1つの目標に掲げています。
今日は、こういったうっかりコーディングミスを未然に防ぐためのZigの仕組みをいくつか紹介したいと思います。
基本的にパターンはあって、機械的に検出できるものはおおいに利用します。そして、これはうっかり忘れたわけじゃないよという意味で、明示的に指定するということになります。要するに「指差し確認!ヨシ!」ということですね。じゃあ、まいりましょう。
まずは、配列の範囲チェックです。これは、だいたい多くの言語で行われていますが、Zigでどうしてもそこのスピードを速くしたいという場合には、あえてこういった指定(@setRuntimeSafety(false);)をすることで、明示的にブロックのみ配列の範囲チェックをオフできます。
それから、変数は宣言時に初期化が必要です。必ず初期化をしなければいけません。初期化しない時には、明示的にundefinedを代入することになります。undefinedが代入している値に、そのままその値を読み込むようなコードを書くと、コンパイラが弾いてくれます。
intという整数型はありません。Cの場合、歴史的にintという型があって、ライブラリでもそこら中intが使われちゃっているわけですが、最近の言語、例えばRustなんかもそうですが、サイズと符合の有無を明確にしてきっちり型を分けます。
u8だとか、i32とか、usizeとかですよね。あと、それによってCだと雑にintと書いてしまうような場面でも、きっちりと区別されます。
暗黙の型変換は、サイズが大きくなる方向にのみ許されています。そうでない場合、@truncateという組み込み関数を使って明示的に切り詰めるとか、あるいはキャストをかけるとか、そういったことをしなければいけません。
ちなみにZigでは、このサイズに上限はあるのですが、任意に指定できます。ですので、6bitのunsignedだったらu6、3bitのsignedだったらi3という型も可能です。これはちょっと後から出てきますので覚えておいてください。
算術演算です。これはデフォルトでオーバーフローがチェックされます。オーバーフローはわかりにくいバグになるんですよね。(スライドを示して)これは足し算の例ですが、普通に書いた場合、オーバーフローのチェックがされます。オーバーフローすると、そこで異常終了して、スタックトレースが表示されるという感じになります。
今までのC言語のように、ラップアラウンドされるようにしてほしい場合には、そういう演算子が別に用意されていて、「+%」という書き方をします。
それから、飽和演算。要するに上限で止まってほしい時には、(スライドを示して)こういった演算子も用意されています。詳しくは、ドキュメントのOperatorsを見てください。
シフト演算。これはたまたま気がついたのですが、すごいですよ。この関数、コンパイルエラーになるんですよ。
xとyと、両方ともi64の場合なんですが、コンパイルエラーが何を言っているかというと、このyの部分は、0から63までじゃないといけないんですよね。なので、i64という変数だとエラーになる。その0から63まで表す変数の型が、実は6bit。要するにunsigned 6bitなので、u6というそういう型なんですよ。
これはどういうふうにしたらコンパイルが通るかというと、実はこんなふうにします。この関数(std.math.Log2Int())を使うとi64の大きさを、シフトできる変数の型を返すんですね。これ、u6という型が返ってきますので、それに対してキャストをかけると、これでコンパイルが通るという感じになります。
これ、本当にチェックが厳しいですね。こんなチェックをするなんて、やはりZigはガチでこういったミスを許さないということがわかります。
次、switch文はすべての場合を網羅する必要があります。これはswitch文の例ですが、Zigの場合はこういうふうに範囲指定をすることもできます。
その他の場合、いわゆるCでいうところのデフォルトをZigではelseと書くのですが、なんにもしない場合でも必ず書かなきゃいけません。この空っぽのカッコは、なんにもしないという意味なんですが、これを省略するとコンパイルエラーになります。
要するに、このxの値はi32なんですが、i32の範囲のどんな値が来ても必ずどれかを通過するようにしなければいけません。それによって、抜けがないことをコンパイラがしっかりチェックしてくれます。
次、関数の引数はimmutable。要するに書き換えできないということです。なぜ書き換えできないかという理由は、ドキュメントにきちんと書いてあるのですが、これをするとどんないいことがあるかなとちょっと考えてみました。
もし、オブジェクトを中で書き換えてもらうように参照、要するにポインターで渡すようにするべきところを間違えて実体渡しにするように書いちゃったとします。
そうすると、渡された側ではそれを書き換えるわけなんですが、immutableなものを書き換えようとしたというのでコンパイルエラーになります。
そうすると、間違いに気がつけるんですよね。これに気がつかないと、書き換えたのに元のものというのはコピーなので、変化がないわけです。そういうなんかわけのわからんバグになるところを、コンパイルエラーになることで気がつくことができます。
次、変数のshadowing禁止。verboseというグローバル変数があるのですが、この関数の中で、このローカル変数で同じ名前のローカル変数を作って、セットしちゃいました。
これって、本当にこれがやりたいことなのかどうなのかがちょっとわかりませんね。実は、グローバル変数を書き換えるつもりだったのに、うっかり手が滑ってここにvarと書いちゃったんじゃないの? という可能性もあるわけですよ。Zigは、そういう紛らわしいことはするなと。名前が被るのはダメとされています。
なので、グローバル変数はあまり使わないほうがいいと思いますし、スコープの広い変数は被りにくいように長い名前にするのがよいかと思います。
次です。未使用だとコンパイルエラー。ローカル変数や関数の戻り値が未使用だとエラーになるのは、Go言語でもそうでした。さらにZigでは、関数の引数も未使用だとエラーになります。
この例では、引数としてx、y、zがあって、zを使っていません。使っていない時には使っていませんよということで、こういう行( _ = z;)を挿入しないとコンパイルエラーになります。
これについてツイートをしたところ、たくさんリツイートされて、意外に反響がありました。
いろいろなことを言われたのですが、私の意見を言っておくと、この「未使用変数でコンパイルエラー」には賛成ですし、たぶん今まで見てきたとおり、Zigの開発チームは、これをオン・オフできるようにするとか、そんなふうに日和ったりは絶対にしないと思います。
やはりこういったチェックがされているほうが、第三者が書いたソースコードを読む時にも、脳の負荷が少なくて済みます。トリッキーなことがあるかどうかという疑心暗鬼にならなくて済むわけです。これは品質の底上げになります。
これが必須になっていることで、要するにこのチェックを通っていないソースコードは、Zigのソースコードとして流通しないということを表しているわけです。
GitHubとかで取ってこられるコードは、基本的にコンパイルが通っているわけで、コンパイルが通っているイコール、こういったチェックを全部通過しているということになります。
確かに試行錯誤する時には煩わしいとは思いますが、この煩わしさを減らすのは、エディタのプラグインの側でなんとか便利にするという方向性のほうがいいかと思います。
AIの時代ですので、賢いプラグインがこれから出てくるかと思います。せっかく新しい言語を使うのであれば、常識をアップデートして新しい常識で臨みましょう、というのが私の意見です。
というわけで、Zig言語はおもしろいですよ。まだまだ話したいネタはいっぱいありますが、今日の発表はこれまでにしたいと思います。
どうもありがとうございました。以上です。
司会者:ありがとうございます。みんな反応がすごい(笑)、反応がすごいな。
ちなみに、Zig言語を私は初めて知りました。最近、tetsu_kobaさんがZig言語っていうのをやっているなと「Twitter」で眺めていたんですが、Zig言語を書くきっかけはあるんですか? 使いたいライブラリがそうだったとか?
小林:2022年の夏頃になんか流行ったんですよ。
司会者:あっ、そうなんだ。
小林:「Bun(バン)」というJavaScriptのランタイムの速いのが登場して、それがこのZigという言語で書いてあると。
それまでもZigはあったんだけど、やはり出たばかりの言語は本当に使いものになるのかという不安があるから、あまり手を出さずにいました。でも、そういうものが作れるんだったらもう実用レベルに近いんじゃないかなと思って。
ブームが来た時に私もちょっと調べていて、その時はコードとドキュメントを見ただけだったんですが、12月頃になってから1回ちょっと自分で実際にコードを書いてみたら、すごくおもしろくて。今は、だいぶ時間を使ってZigを調べたりブログの記事に書いたり、そんな感じですね。
なにしろ、まだマイナーなので使っている人が少ないでしょう? だからなるべく、いろいろな人を引き込んでいきたいなと思ってもう一生懸命宣伝しています。みんな、Zigやろうよ(笑)。
司会者:なるほど。「そういう言語だったんだ」という感想をされている方がけっこう多かったので、目的にかなったかなと思います。ありがとうございました。
※なお、この発表のスライドと動画は発表者本人のブログから見ることができるようになっています。「https://zenn.dev/tetsu_koba/articles/c039b865114b93」
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.12
今までとこれからで、エンジニアに求められる「スキル」の違い AI時代のエンジニアの未来と生存戦略のカギとは
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05