2024.10.10
将来は卵1パックの価格が2倍に? 多くの日本人が知らない世界の新潮流、「動物福祉」とは
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.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略