- Zigのcomptime機能は非常に強力なコンパイル時評価機能を提供するが、意図的に制限されている
- コンパイル時のコード実行ではホスト情報にアクセスできず、クロスコンパイルに適した設計になっている
- 動的コード生成、DSL、RTTI、I/Oなどはサポートしないが、代わりに明示的な型ベースのコード特殊化を使う
- RTTIは自前で実装可能で、コンパイル時にしか存在しない型情報をランタイムで使えるよう再構成できる
- comptimeで新しい型は生成できるがAPI拡張は不可で、ユーザー定義メソッドの追加はできない
Zigのcomptimeがしないこと
- Zigのcomptimeはジェネリクス、条件付きコンパイル、シリアライズ、ORMなど強力な機能を提供する一方で、一部の機能は明示的に制限されている
- その制限こそが、Zigの設計を簡潔で予測可能なものにしている
-
ホスト情報にアクセスできない (No Host Leakage)
- comptimeコードはコードが実行されるシステムではなく、ターゲットプラットフォームを基準に動作する
- Zigではコンパイル時にホストシステムのエンディアン、ポインタサイズなどの情報を使えない
- これはクロスコンパイルを考慮した安全性の確保が目的
- 例のコードではBF16形式の数値のバイト出力がターゲットプラットフォームによって異なる
-
文字列ベースのコード生成はない (No #eval)
- ZigはCの
#include、D言語のmixin、Rustマクロのような動的にコードを生成する機能を提供しない
- その代わり、**comptime引数ベースの部分評価(partial evaluation)**をサポートする
- 特定の引数がコンパイル時に分かっていれば、その分岐だけが残り、コードの最適化が可能
-
DSLの構文拡張はできない (No DSLs)
- ZigではLispやRustのようにユーザー定義構文(syntax)を作る機能はない
- すべてのデータはZig構文に従う**値(value)**の形でのみ渡される
- フォーマット文字列(
printf)のような限定的なDSLはcomptime文字列だけで実装できる
-
ランタイム型情報はない (No RTTI)
- ZigはPythonのような動的言語のように振る舞えるが、型情報はcomptimeにのみ存在する
- ランタイムでも動作させたければ、自分でRTTI構造体を定義し、ポインタで操作しなければならない
- 例: structフィールドの名前とオフセット情報を持つ
RTTI構造体を定義し、ポインタでフィールドにアクセスする
-
新しいAPIは生成できない (No New API)
- Zigではcomptimeで新しい型を作ることはできても、その型にメソッドを追加することはできない
- Rustのderive macroのようにAPIを拡張することはできない
- JSONシリアライズ実装では
.to_json()メソッドを追加できず、グローバル関数に型引数を渡す方式で実装する
-
コンパイル時IOはない (No IO)
- Zigのcomptimeはファイルシステム、ネットワーク、データベースなどの外部リソースへのアクセスを禁止している
- そのため再現可能性、安全性、キャッシュ活用性が高まる
- IOが必要なら、buildシステムである
build.zigを使って事前生成したZigコードをimportする方式を使う
-
まとめ: El Disco (抽象化と単純性のバランス)
- Zigは強力なメタプログラミング機能を提供しつつ、非常に制限的な設計によって予測可能性を確保している
- この制限のおかげで、Zigのcomptimeは実用的で理解しやすい形に保たれている
- 複雑な抽象化がなくても実運用で有用であり、宣言された機能だけが明確に動作する
1件のコメント
Hacker Newsの意見
Zigのcomptimeは独特な特徴を持つ
Zigのcomptimeの欠点と解決策
zig buildでコード生成後、@importしてコンパイルするBorgesの物語から引用されたスペイン語の文句は、ノルウェーの神に関するものである
comptimeの柔軟性
Zigのcomptime機能で有名な点
教育的なブログ記事
comptime forとinline forの違いを説明するZig言語とツールに対する肯定的な意見
Zigのcomptimeに関する興味深い点
コンパイル時コード実行に関する混乱