- C言語の文法と意味を継承しつつ、安全性と使いやすさを強化した進化型言語で、既存のC開発者にとってなじみのある環境を維持
- 完全なC ABI互換性を提供し、C/C++プロジェクトにそのまま統合可能。vkQuakeの一部コードがC3に変換され、c3cコンパイラでビルドされた事例あり
- モジュールシステム、演算子オーバーロード、コンパイル時マクロなどにより、コード構造と表現力を向上
- 契約ベースプログラミング(Gradual Contracts)、ゼロオーバーヘッドのエラー処理、ランタイムおよびコンパイル時リフレクションなどの現代的機能を含む
- デバッグモードでは安全性チェックと詳細なスタックトレースを自動提供し、バグ検出と安定性確保に有利
C3 概要
- C3は、C言語の**文法(syntax)と意味(semantics)**を基盤として発展したプログラミング言語
- 目標は、既存のCプログラマになじみのある形を保ちながら、言語を進化させること
- 正確で目的指向の演算子オーバーロードをサポート
- C++の複雑なオーバーロード構造なしに、ベクトル、行列、固定小数点演算を自然に表現可能
- 契約ベースプログラミングをサポートし、ランタイムおよびコンパイル時の制約を明示可能
- Resultベースのエラー処理と**例外(exception)**の長所を組み合わせる
- **型情報参照(type introspection)**をコンパイル時とランタイムの両方でサポート
- インラインアセンブリ:文字列や複雑な制約なしに、通常のコードのようにアセンブリを記述可能
- デバッグモードでランタイムの**境界チェック(bound checks)と値チェック(value checks)**を自動挿入
- C3標準ライブラリはデバッグビルドで詳細なスタックトレースを標準提供
- 単なる「segmentation fault」ではなく、具体的なエラー位置を確認可能
Ergonomics and Safety
- Optionalsによりエラーとnull処理の安全性を提供
- defer構文でリソース解放の自動化をサポート
- slicesとforeachで安全な反復処理が可能
- コメントベースのcontractsでコードの制約条件を明示可能
- @poolコンテキストでメモリの自動解放をサポート
Performance by default
- SIMDベクトルを直接記述し、ハードウェアレベルの制御が可能
- さまざまなメモリアロケータの選択により性能の微調整をサポート
- エラー処理でオーバーヘッドのない設計を採用
- 高速なコンパイル時間とLLVMバックエンド最適化を活用
- 使いやすいインラインアセンブリを提供
Batteries included standard library
- 動的コンテナや文字列を含む標準データ構造を提供
- クロスプラットフォーム抽象化によりプラットフォーム間の移植性を確保
- 必要に応じてネイティブプラットフォームへのアクセスを許可
Leverage existing C or C++ libraries
- C3はC ABIと完全互換であり、別途「C互換型」や関数宣言は不要
- C3からCコードをリンク可能で、CからもC3コードをリンク可能
Modules are simple
- シンプルで直感的なモジュールシステム
- デフォルト設定が合理的に構成されており、開発フローを妨げない
- モジュールによる名前空間管理を提供
- 明示的な制御でカプセル化構造を簡素化
- インターフェースで共有動作の定義が可能
- ジェネリック型の生成をシンプルかつ明確に実装できるgeneric modules機能を提供
- 構造体サブタイピングによる構造の再利用をサポート
Macros without a PhD
- コンパイル時マクロを通常の関数に近い形で記述可能
- コードの型情報を理解する型認識マクロをサポート
- Cのプリプロセッサよりも明確で強力なコード生成をサポート
4件のコメント
いろいろ出てきていますね。LONG LIVE C-LANG !!!
でも後でc4が出てきたら、まさに爆発的な人気になるのでしょうか…
Zig は毎年 breaking changes が入るので、言語自体は気に入っているのですが、もう手が伸びなくなってきました。
一方で C3 の紹介を見ると、全体的に C + Go のような感じで読み書きしやすく、バージョンアップによるストレスもずっと少なそうな印象ですね。
少しは支援もしつつ……最近使っているんですが、面白いです。
Cをやっていて不便だった点だけを改善しようとしている感じで、そこがいいですね。
公式ドキュメントはまだあまり成熟しておらず、
(あれこれ機能を調べようとすると、思いがけない場所に書かれていることが多いです……)
Hacker News の意見
新しいメモリモデルを強要せず、C++のようになろうともしていない
特に完全なABI互換性のおかげで、既存のCビルドシステムにそのままC3ファイルを混ぜて使え、バインディングを書く必要がなくなる
革命より進化を目指すメンテナーのビジョンに拍手を送りたい
週末に学んでみる言語として勧められる。C99よりモダンだが、なじみのある感じだ
自分がCを完全に捨てきれない理由はcstringと解放されないポインタにある
C自体が危険な言語というより、実装とABIが危険なのだ
fat pointer、varargsの改善、UBSan、MTEなどを適用すればかなり良くなる
コンパイラが契約を必ず検査しなくてもよく、違反時に未定義動作になりうるなら、これをどう信頼して使えばいいのかわからない
すばらしい機能だが、やや危険に見える
これを無視したり、ランタイムで検査したり、あるいは常に真だと仮定して最適化に利用したりできる
たとえばポインタの妥当性は検査し、奇数入力条件は仮定として置く、といった選択が可能だ
大規模チームでは強制できるし、Visual Studioのようなツールは警告だけを出して段階的に学べるようにする
つまり、開発中は有効にし、配布時には無効にして性能への影響をなくせる
必ず検査すべき条件は関数内で直接コードとして処理すべきだ
Cとの違いとしては、ヘッダーファイルなし、モジュールベースの名前空間、スライス、演算子オーバーロード、ジェネリックモジュール、Resultベースのエラー処理、セーフモードでのランタイム検査などがある
個人的には関数オーバーロード、デフォルト引数、タプル返却が欲しい
ResultやExpectedをOptionalと呼ぶのは紛らわしい「T または空」ではなく「T または E」を意味すべきなのに、名前が間違っているように思える
関連ドキュメントへのリンク
Option<T>やResult<T, E>とは異なるエラー型が整数コード1つに制限されていて、これは「革命ではなく進化」という思想によく合っている
type?構文も直感的だCの意味を保ちながら、out paramの負担を減らす設計だ
Resultはすでに一般的な返り値の意味を持つので混乱を招く可能性があるYouTubeプレイリスト
3つの言語が競争するというより、互いのトレードオフを共有しながら学ぶ関係である点が印象的だった
その代わり、マクロやリフレクションのような機能が追加されている
最も大きい型ぶんのメモリを占有し、ランタイム型検査へと流れが移るので、静的型付け言語の利点を失ってしまう
必要なときに自分で実装するほうがよいと思う
Cでジェネリクス、スライス、エラー伝播を自前実装したが、コンパイラ制作は複雑すぎる
だから私はCの派生とGoを並行して使っている
1日でプロトタイプを作れるほど、参入障壁は低い
新しいパラダイムを現実のものにする唯一の方法だからだ
言語は文法、標準ライブラリ、ツーリング、ランタイムまですべてを調整しなければならないので難しいが、そのぶん未来への影響も大きい
LLVMのおかげで新しいコンパイラを自作できた
1人で使うC派生なら問題ないが、他人と協業したり外部ライブラリを使ったりするには共通言語が必要だ
そして例外を「Excuses」と呼ぶ点がかわいくて気が利いている
特にナビゲーションにDiscordリンクがあるのが、その印象を強めている