Yulang
yulang
if all [1, 2, 3] < any [4, 5, 6]:
"found a pair"
else:
"nothing"この if は、左のリストの要素ひとつひとつを、右のリストの要素全部と比較しています。ループも内包表記も補助関数もありません。all と any がただの値で、比較演算子の方がそれらを持ち上げるからです。同じ仕掛けが、非決定的な探索にもそのまま効きます。
yulang
{
my a = each 1..
my b = each a<..
my c = each b<..
guard: a * a + b * b == c * c
(a, b, c)
}.once3 つの each が、無限に広がる 3 次元の格子を探索します。guard で枝刈り、.once で「最初に見つかった 1 件」を取り出す。書かれているコードは上から下にまっすぐ流れているのに、裏側では分岐と backtrack が走っています。
Yulang の中心にあるのは、「制御構文はライブラリで書く」 という方針です。可変参照も、非決定性も、all / any のような集合的な比較も、early return も、型付きエラーも、独自の backtrack も — どれも parser が抱える builtin ではなく、代数的エフェクトという 1 つの仕組みの上に乗った普通の関数です。表に出るコードは短くて直線的なまま、裏側の形だけを好きに広げられます。
中に入っているもの
- 代数的エフェクトと handler。
actで operation を宣言し、catch op, k -> ...で受けます。handler は捕まえた継続kを受け取るので、再開・再試行・中断はすべて「kをどう扱うか」の選択として書けます。 - typeclass じゃなくて role。
role Add 'a:で interface を宣言し、impl Add int:で実装。method は普通のドット呼び出しに見えます。 - 可変な local binding。
my $x = 0で宣言、$xで読み、&x = vで書く。中では handler 付きのvareffect に展開されるので、意味論は純粋なまま、書き味は素朴です。 - binding の左辺は全部 pattern。
my (a, b) = pairも、record pattern + default で書く optional 引数my area {width = 1, height = 2} = width * heightも、同じ binding の形です。 - 括弧少なめの表面。 bare application
f x y、colon applicationf: ...、:とインデントで開く layout block。
Playground
このページの例はすべて Playground でそのまま動きます。