LP-9

デスクトップの業務画面を書くための、アクタを持つ関数型 Smalltalk

羽田空港の画面。滑走路と誘導路、駐機場の機体

LP-9 は、Windows と Linux のデスクトップで動く画面を書くための言語です。受注の一覧と入力、明細と保存、監視盤、地図の上を動くもの、タスクトレイに常駐する道具。業務の画面も、毎コマ動き続ける画面も、同じ書き方で書けます。

上の絵は、LP-9 と一緒に配っている羽田空港の画面です。どう動いているかは、このページの中ほどで説明します。

業務の画面が、そのまま書ける

受注一覧の表。伝票番号、納期、品名、数量、金額

一覧、入力欄、ボタン、チェックボックス、コンボボックス、日付、ツリー、表、ダイアログ、子ウィンドウ。業務の画面に要る部品は最初から揃っています。

キー操作は、利用者が Windows の業務アプリで慣れているものに合わせています。Tab と Shift+Tab で項目を移り、Space と Return でボタンを押し、保存(&S) と書いたボタンは Alt+S で押せます。Escape でダイアログを閉じると、フォーカスは開く前の場所に戻ります。コンボボックスは F4 で開きます。画面ごとに書かなくても、ランタイムがそう振る舞います。

画面のプログラムは「何を描くか」を返すだけで、描くのはランタイムです。前と同じものを返した所は描き直さないので、行が何百あっても、変わった行だけが描かれます。

動かす前に、誤りが分かる

型は一つも書かなくてよく、全部推論されます。そのうえで、次のような誤りはプログラムが動き始める前に見つかります。

業務の画面は、作ったあとに何年も直し続けるものです。誰かが一か所を直したとき、それで壊れた別の場所が、利用者の手元ではなく作った人の手元で見つかります。

VS Code の拡張は、打っている間に同じ検査をして誤りを示します。型を書かない代わりに、カーソルを置けば推論された型と、それがどこで決まったかが見えます。

金額と日付が、最初から正しい

1234.50s と書いた数は十進の正確な数(Decimal)で、二進の浮動小数点ではありません。割り算には、結果の桁数と丸め方を必ず書きます。四捨五入、切り捨て、銀行の偶数丸めのどれを使ったかが、コードに残ります。画面に出すときは grouped で三桁ごとに区切れます。

日付(Date)は暦の日付で、時刻やタイムゾーンに引きずられません。1 月 31 日の一か月後は 2 月の末日です。JSON の小数は桁を落とさずに読み、データベースとの間も型のまま受け渡します。

日本語が、正しく扱える

日本語入力の画面。変換中の「日本語」と三つの候補

日本語入力の変換中の文字と候補は、入力欄の中のキャレットの位置に出ます。複数行の入力欄は、行頭に来てはいけない文字(、。」 など)を守って折り返します。フォントは Windows なら游ゴシック、Linux なら Noto Sans CJK を使います。

動き続ける画面も、同じ書き方で

280 個の計器が並ぶ監視盤。範囲を外れた計器が赤い

監視盤の計器の一つ一つ、地図の上の機体の一つ一つを、それぞれ独立に動くもの(アクタ)として書けます。上の監視盤には 280 個の計器があり、どれも自分の間隔で値を変えます。スレッドもロックも、全体を動かす時計も書いていません。一コマに描き直すのは、変わった計器の分だけです。

一つのアクタが処理の途中で失敗しても、止まるのはそのアクタだけで、プログラムは動き続けます。止まったことを別のアクタが知らされ、そこで立て直せます。

通信やデータベースのように待つ処理は、別のスレッドに置けます。置き場所を指定するだけで、送る側の書き方は変わりません。待っている間も画面は止まりません。

例:羽田空港の画面

このページの最初の絵の羽田空港の画面も、この書き方で動いています。滑走路 4 本、誘導路 750 本の上を、機体が地上を走り、離陸し、着陸します。

機体は一機ずつアクタです。 機体の位置と、駐機中・地上走行中・離陸待ちといった段階は、その機体のアクタだけが持っています。機体は少し待ってから自分に「次の一歩」のメッセージを送り、それを受け取って進みます。機体ごとに自分の間隔で動くので、全部の機体を一斉に動かす時計も、機体の一覧を回すループもありません。

滑走路は管制塔のアクタだけが持っています。 空港の中で、同時に一機しか使えないのは滑走路です。誰が使っているか、誰が待っているかは、管制塔のアクタの状態にしかありません。機体は停止位置まで来ると、管制塔に「使わせてほしい」と送ります。管制塔は、空いていれば許可を返し、空いていなければ待ちの列に入れます。滑走路を出た機体が「空いた」と知らせると、列の先頭の機体に許可が届きます。

ここにロックはありません。管制塔はメッセージを一つずつ処理するので、二機に同時に許可を出すことが起きないからです。待ちの列ができるのは、許可のメッセージがまだ届いていない、というだけのことです。

機体は毎回、自分の位置を管制塔に知らせます。 管制塔は全部の機体の位置を知っているので、すぐ前に別の機体がいれば「止まれ」と返します。機体どうしが互いの位置を直接見に行くことはありません。

左下の交信欄は、実際のやりとりです。 管制塔は、頼みを受けたときと許可や待機を返したときに、同じ処理の中で交信欄のアクタにも送ります。表示のために別に作った文はなく、画面に出ているのはアクタの間で実際に起きたことです。

描き直すのは、動いた機体の所だけです。 画面は、地図、機体の一機ずつ、交信欄、管制塔の表示を、それぞれのアクタに任せています。止まっている機体や地図は前のコマと同じものを返すので、描き直されません。

この画面は、特別な機能を使っていません。業務の一覧や入力の画面と同じ仕組みで書いてあります。

配りやすい

lp9 build で、ネイティブの実行ファイルが一つできます。Windows では SDL3 の DLL を横に置くだけで、利用者の機械に言語のランタイムを入れる必要はありません。

画面を、ウィンドウを開かずに確かめられる

画面のプログラムに、クリック、キー、打った文字、日本語入力の途中の状態を引数で渡して、描いた一コマを画像に書き出せます。人が画面を操作しなくても、画面の振る舞いを自動の検査に入れられます。

開発中は解釈器ですぐに動かし、配るときはネイティブにビルドします。二つは同じ答えを出し、同梱の検査は全部を両方で実行して、出力を一バイトずつ比べています。

データベースと通信が、最初から入っている

SQLite、PostgreSQL、MariaDB・MySQL、HTTP、TLS、JSON、MessagePack、正規表現、ファイルと子プロセス。どれも追加のライブラリなしで使えます。SQL の引数は名前で渡し、名前を間違えると NULL として黙って通るのではなく、エラーになります。SQL のコメントに条件を書く二方向 SQL も使えます。

書くとこうなる

ボタンを押すたびに数が増える画面です。

imports: (Ui, Theme).

Object subclass: #Bump fields: ().

Actor subclass: #Counter fields: (n).
Counter class >> start = Counter fields: { n: 0 }.
Counter class >> title = 'Counter'.
Counter class >> width = 320.
Counter class >> height = 160.

Counter >> theme = Theme day.
Counter >> Bump = self copyWith: { n: n + 1 }.

Counter >> view = Paint group: #[
        Paint rect: 0 y: 0 w: 320 h: 160 color: #paper,
        Paint move: (Paint column: #[
            W label: ('pressed ' , n asString , ' times'),
            W gap: 20,
            (W button: 'Press' wide: 120) on: #click send: Bump ] gap: 0) x: 24 y: 28 ].

画面の状態は n だけです。ボタンを押すと Bump が届き、Counter >> Bump が次の状態を返し、画面はその状態から描き直されます。クリックも、キーも、通信の答えも、時計の一刻みも、全部この形で届きます。

書き方の詳しいことは言語の設計、画面、アクタにあります。

実行環境

Windows と Linux の x86_64 で動きます。lp9 という実行ファイル一つが、解釈器、ビルド、言語サーバ、デバッガを兼ねます。VS Code の拡張が付属しています。

LP-9 は、サーバで常駐するサービスを書くための Lambda Prelude のデスクトップ版です。言語の形は Lambda Prelude と同じで、サーバ側と画面側を同じ考え方で書けます。ブラウザで動く画面には LPScript があります。

ライセンスとお問い合わせ

LP-9 は プロプライエタリソフトウェアであり、すべての権利は 合同会社 Lambda に帰属します。LP-9 の複製・改変・再配布には、合同会社 Lambda による書面での事前許可が必須 です。OSS ではありません。

バイナリ(lp9 本体、標準ライブラリ、エディタ拡張)は 無償・無保証・現状有姿 (as-is) で提供します。評価・利用は すべてご自身の責任 で行ってください。特定用途への適合性は保証しません。別途契約しない限りサポートは提供せず、利用に起因する一切の損害について責任を負いません。

ソースコード は NDA を締結したパートナー企業にのみ開示します。この NDA および付随する個別契約が、ライセンス本文で要求される「書面での事前許可」にあたります。ソース開示は 有償案件(共同開発・カスタマイズ・統合)とセット であり、ソース単体での販売は行いません。

業務アプリの開発や本番運用での LP-9 利用をご検討の場合は、お気軽にご相談ください。主に以下の 3 つの形態でご一緒します。

ご相談は 合同会社 Lambda までお寄せください。