ソースからビルド
Lambda Prelude は OCaml ソースを dune でビルドする。
# 必要環境: OCaml 5.4+ / dune 3.0+ / menhir 2.1+
git clone <repo-url> lambda_prelude
cd lambda_prelude
dune build
Windows では出力バイナリは真のネイティブ MinGW-w64 実行ファイル (実行時 Cygwin DLL 非依存)。ソース開示は NDA ベースのため、本番評価をご検討の際は事前に お問い合わせ ください。
Hello, Prelude
hello.lp を作成する。
'Hello, Lambda Prelude!' printNl.
インタプリタで実行する。
lambda-prelude run hello.lp
ネイティブバイナリにビルドする。
lambda-prelude build hello.lp --out hello
./hello
インタプリタは反復開発用。意味の正典は AOT バイナリ — インタプリタと AOT が食い違ったら AOT バイナリが勝つ。
カウンタクラス
Lambda Prelude は関数型で、値は不変、クラスはインスタンス変数を持たない。各オブジェクトは fields: 上の不変レコード。
Object subclass: #Counter fields: (value).
Counter class >> of: n = Counter fields: { value: n }.
Counter >> value = value.
Counter >> inc = Counter fields: { value: value + 1 }.
c := Counter of: 41.
c inc value printNl. "=> 42"
inc は新しい Counter を返す。ユーザコードに := 再代入はない — 束縛は let (トップレベルでは :=) のみ。
分岐は多態ディスパッチ
表層に if / match は存在しない。分岐はすべてメッセージ送信で書く。
(score > 90)
ifTrue: ['A' printNl]
ifFalse: ['B' printNl].
name ifPresent: [:n | n printNl]
ifAbsent: ['anonymous' printNl].
xs ifEmpty: ['empty list' printNl]
ifNotEmpty: [:h :t | h printNl].
これは伝統的な Smalltalk と同じ流儀を、条件分岐 / Option 分解 / リスト分解 / retry / timeout すべてに一貫して適用したもの。
プロトコルが継承の代替
クラスは継承しない。共通振る舞いは型クラスに相当する Protocol で表現し、クラスは protocols: 節で実装するプロトコルを宣言する。
Protocol subclass: #Comparable
requires: (#<).
Comparable >> > other = other < self.
Comparable >> min: o = (self < o) ifTrue: [self] ifFalse: [o].
Comparable >> max: o = (self < o) ifTrue: [o] ifFalse: [self].
Object subclass: #Score
fields: (points)
protocols: (Comparable).
Score class >> of: n = Score fields: { points: n }.
Score >> points = points.
Score >> < other = points < other points.
((Score of: 10) max: (Score of: 3)) printNl.
Score は < だけを実装すれば > / min: / max: が Comparable 経由で自動的に手に入る。
2 つの実行モード
同じソースを 2 通りに実行できる。標準ライブラリ・型システム・アクターモデルは共有される。
| 機能 | インタプリタ | AOT |
|---|---|---|
| ツリーウォークによる反復開発 | あり | — |
| 静的に解決できる送信を OCaml 直接呼び出しに | — | あり |
| 動的送信用ランタイムディスパッチャ | あり | あり |
| マルチドメインワークスティーリングスケジューラ | あり | あり |
Dynlink プラグイン (PostgreSQL / MariaDB / MySQL / Redis) | あり | あり |
反復開発は run、本番は build — AOT バイナリは静的に解決できる送信を直接 OCaml 呼び出しに落とし、それ以外は実行時のメソッドディスパッチを通す。
CLI リファレンス
lambda-prelude run script.lp # ツリーウォークインタプリタ
lambda-prelude build script.lp --out binary # AOT ネイティブ
lambda-prelude test tests # Test API のテスト実行
lambda-prelude new my-service # プロジェクト雛形
デバッグツールは次のとおり。
lambda-prelude run script.lp --trace-mailbox # メールボックス投入 / 受信を逐次ログ
lambda-prelude run script.lp --quiet # 未マッチメッセージ警告を抑止
lambda-prelude run script.lp --scheduler multi 4 # N ワーカードメインプール + 自動分散
lambda-prelude build script.lp --emit # 生成された OCaml を標準出力に
lambda-prelude build script.lp --out script.ml # 生成された OCaml をファイルに