ソースからビルド

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 をファイルに

次のステップ