世界を動かす技術を、日本語で。

OCamlcのための新しいC++バックエンド

概要

このパッチは、 OCaml のコンパイラ ocamlc に新しい C++バックエンド を追加 従来のC実装よりも 可読性と機能性 が向上 C++コードは 純粋関数型 スタイルで生成されるため、OCaml標準ライブラリの一部が利用不可 C++インタプリタ(例: g++)でコマンドライン引数を渡して実行可能 今後は他言語(例: Rust)への展開も視野

OCaml → C++ バックエンド導入の概要

  • ocamlc に新たな C++バックエンド を追加
  • 既存のCバックエンドよりも 可読性拡張性 を重視
  • 例として、 ユーザ指定の上限までの素数列挙プログラム を紹介

OCamlコード例(素数列挙)

  • List モジュールの一部を 純粋関数型 で再実装
  • filter 関数や init 関数を再定義し、リスト操作を実装
  • primes 関数でエラトステネスの篩による素数列挙を実現
  • main 関数でユーザ指定のlimitまで素数を計算

C++コード生成と特徴

  • コマンド: ocamlc -incr-c primes.mlprimes.cpp が生成
  • 生成されるC++コードは テンプレートメタプログラミング を多用
    • 例: Cons 型でリスト表現、 I<n> 型で整数表現
  • 可変状態(ミュータブル) が使えないため、OCaml標準ライブラリの多くが利用不可
  • :: 演算子が使えないため、 Cons<hd, tl> 形式でリストを表現

実行方法と出力

  • g++ 等のC++インタプリタを利用
  • コマンド例: g++ -Dlimit=100 primes.cpp
  • 出力は ネストされたCons構造体 としてエラー文に表示
    • 例:Cons<I<2>, Cons<I<3>, ... I<97>, I<0>>>
  • main 関数引数は -Dlimit=値 オプションで指定

パフォーマンスと制限

  • 大規模計算時は テンプレート再帰の深さ 制限に注意
    • 例: -ftemplate-depth=999999 オプションで拡張可能
  • g++ は大きな入力で高メモリ消費(例:11GiB/10000までの素数)
  • clang++ は高速だが、動作や出力が異なる場合あり
  • アルゴリズム改善で 計算効率 向上可能
    • O'NeillやOkasakiのアルゴリズムを利用することで大幅に高速化

今後の展望

  • 本アプローチは 他言語バックエンド への展開が可能
    • 例: Rust が部分的なimpl特殊化をサポートすればOCamlプログラム実行が可能に
  • 純粋関数型スタイル のコード生成を他言語でも活用可能性

まとめ

  • OCaml のC++バックエンドは 純粋関数型 に特化し、 C++テンプレート を駆使
  • 標準的なC++では ミュータブルなライブラリ が使えない制約あり
  • 可読性の高いC++コード が自動生成されるため、保守性や解析性が向上
  • 大規模な計算他言語対応 など、今後の発展が期待される

Hackerたちの意見

素晴らしい内容ですね。長く続くC++を書くためのヒントですが、なんとC++のインタプリタはテールコール最適化がまったくないんです。そのせいで、ほとんどのイディオマティックなC++コードは、スタックを吹き飛ばさないように、reverseやmap、range、filterなどを実装して使っています。例えば(擬似コードを許してください):

(defun fibreverse (i ret acc) (if acc (if (> i 0) (progn (setv call1 (fibreverse (- i 1) (cons (head acc) ret) (tail acc))) (setv ret1 (head call1)) (setv acc1 (head (tail call1))) (if acc1 (fibreverse (- i 2) (cons (head acc1) ret1) (tail acc1)) (pair ret1 acc1))) (pair ret acc)) (pair ret acc)))

(defun reverse (list) (head (fibreverse 30 nil list)))

あなたがいなくなった後にコードをメンテナンスする人は、コマンドラインフラグに頼るのではなく、イディオマティックでポータブルなアプローチを使ったことを感謝するでしょう。

これって「movはチューリング完全」って有名なスティーブン・ドランですか?

そう思う。

これってjqのクリエイター、スティーブン・ドランなの?

彼女(ジェーン・ストリート)は、君のことなんて気にしないよ、兄弟。

彼らはもうジェーン・ストリートで働いていると思うよ。

これで今日が良い日になった、ありがとう!

これらのより洗練されたデータ構造を使うことで、g++は10000未満の素数をわずか8秒で計算でき、メモリは3.1 GiBと控えめです。やっとノートパソコンで素数が取れる!

わあ、スティーブン・ドランはいつも感心させてくれるね。

"あなたのプログラムを慣用的で読みやすいC++コードに翻訳したprimes.cppを生成します。" C++好きとして、これは本当に素晴らしい慣用的で読みやすいC++コードだって確認できるよ。

ほとんどはそうだけど、これについてはどう思う? typedef I::val) != (I::val))> res; }; ここにはトップクラスの魔法が使われてるよ!C++で型定義の中に条件を使ったことなんてないかも :)

"C++は純粋な関数型言語です"って聞いて眉が上がったけど、ただのタイプミスだと思った。残りは素晴らしいし、タイプミスじゃなくてよかった!