はじめてのアプリ
Rakugan(落雁)を使うと、Perl で書いたデスクトップアプリを 1 本のネイティブバイナリとしてリリースできます。
rakugan build は、書いた Perl を pixie に翻訳し、Zed エディタを支える gpui の上に組んだ pixie のエンジンと結びます。
書いているあいだは、同じファイルを perl が動かします。
このとき perl は小さな XS モジュールを通して同じエンジンに触ります。
配るバイナリと、書いているあいだの実行が同じプログラムかどうかは、rakugan gate で確かめます。
一つのスクリプトで両方を動かし、描いた画面を 1 バイトずつ突き合わせます。
画面を組み立てるサブルーチン(text、button、column など 30 あまり)は Rakugan が用意しますが、アプリそのものは普通の Perl のクラスです。
書ける Perl の範囲は、このツアーが説明する方言です。
そこから外れる書き方はRakugan が断る書き方に挙げてあります。
アプリはクラスで、状態はそのフィールドです。 型を書く場所は二か所だけです。
いちばん小さいアプリ
アプリは view メソッドを持つクラスです。
view は要素を一つ返し、そのクラスのインスタンスを run に渡すとウィンドウが開きます。
use Rakugan; はファイルの先頭と、クラスの中の 1 行目に書きます。
Perl の import はパッケージごとに効き、class App { ... } はそれ自体が一つのパッケージだからです。
use Rakugan;
class Hello {
use Rakugan;
method view {
return text("hello", size => 28);
}
}
run(Hello->new, title => "hello");
$ rakugan run demo/hello.pl # perl でウィンドウが開く
$ rakugan gate demo/hello.pl --script "dump"
GATE OK — 1 dump line identical in both runs
アプリを動かす perl は 5.40 以降です。
class を機能として当てにできるのは、そこからだからです。
コマンド自身は、パスの先頭にある perl で動きます。
状態の持ち方
状態はクラスのフィールドです。 ハンドラは無名サブルーチンで、その中からはフィールドがそのまま見えます。 だから書き換え方は、普通のメソッドと変わりません。 ハンドラを抜けると、そのときのフィールドからビュー全体が組み直されます。
use Rakugan;
class Counter {
use Rakugan;
field $count = 0;
field $name = "";
method view {
return column(
text("count: $count", size => 34),
row(
button("+1", on_click => sub { $count += 1 }),
button("+10", on_click => sub { $count += 10 }),
button("reset", on_click => sub { $count = 0 }),
spacing => 8,
),
text_field($name, placeholder => "your name",
on_change => sub ($s) { $name = $s }),
text("hello, $name"),
spacing => 12,
padding => 16,
);
}
}
run(Counter->new, title => "counter");
ストアを別に用意することはありません。
監視の設定を書く必要も、new を自分で書く必要もありません。
状態はフィールドの初期値から始まります。
型はどこから来るか
Rakugan には型がありますが、そのほとんどはどこにも書きません。
フィールドの型は初期値から読みます。
= 0 なら Int、= 0.0 なら Num、= "" なら Str、= false なら Bool です。
空で始まる入れ物には読むものがないので、何を入れるかをそこで言います。
引数を取るメソッドは、その引数が何かを属性で言います。
method add :Sig(Int) ($by) { $count += $by }
method label :Sig(Int, Str => Str) ($n, $unit) { return "$n $unit" }
:Sig(A, B => R) は、引数の型と、そのメソッドが返すものです。
何も返さないメソッドは矢印を書きません。
引数のないメソッドには属性そのものが要りません。
型の名前は Types::Standard のつづりで、Int、Num、Str、Bool、ArrayRef[Int]、HashRef[Str]、それに自分で書いたクラスの名前です。
残りはすべて Rakugan が計算します。
my で作った名前は、そこに入れたものの型になり、式の型は、その中身から決まります。
食い違いは、実行して初めて分かるのではなく、行番号とともに示されます。