ある程度の規模のプログラムを作ろうと思った場合、制御構造は必須になります。 最低限IfThenElseやWhile構文、できればFor構文やForEach構文もあれば便利です。
それらの構文を実現するためには、最低限真偽判定が必要です。 また、真偽の条件の組み合わせ、つまりandやor、notなども無いといろいろと厳しいでしょう。 ここでは、真偽型(boolean型)と、各種論理演算の実装を行います。
Unlambdaには、当然の事ながら組み込みのboolean型というものはありません。 ですので、適当な関数もしくは関数の組み合わせを独自に定義する事になります。
公式ページでは4種類のboolean型の例が提示されていますが、 一般的によく使われているのは次の二つのbool型だと思います。
その1 true = i false = v その2 true = k false = `ki
このサイトでは便宜のため、前者をvi-bool、後者をki-boolと呼ぶ事にします。
正直、これが一番便利です。
とっても簡単です。
``BTF
のように書けば、真偽値B
が真ならばT
を返し、
偽ならばF
を返します。
どうしてこうなるのかというと、こうなるようにki-boolは定義されているからです (←当たり前)。 では、自分でこの関数と同様の働きをする関数を書いてみましょう。
2引数$t, $fをとり、$tを返す関数(=true)。 ^t^f$t = ^t`k$t = k 2引数$t, $fをとり、$fを返す関数(=false)。 ^t^f$f = ^ti = `ki
ほら、ちゃんとki-boolと同じ関数になりましたね?
andやorを実現するために、スマートな方法は特にないようです。 がんばってif分岐を繰り返して、目的の値を得ます。 以下のコードには、参考としてC言語風の簡単な注釈をつけてあります。
与えられた引数がk
なら`ki
を返し、
`ki
ならk
を返します。
簡単なので、条件分岐の練習のつもりで書いてみましょう。
# if($b) { return false } else { return true } ^b``$b`kik = ``s``si`k`ki`kk
以後この関数を<ki-not>
と称します。
引数を2つとり、最初の引数がk
なら2番目の引数をそのまま返し、
最初の引数が`ki
なら`ki
を返します。
書いている内容はまだるっこしいですが、要するにandです。
# if($a) { return $b } else { return false } ^a^b``$a$b`ki = ^a``s$a`k`ki = ``ss`k`k`ki
以後この関数を<ki-and>
と称します。
面倒なので、まとめてやってしまいます。
# <ki-or> # if($a) { return true } else { return $b } ^a^b``$ak$b = ^a`$ak = ``si`kk # <ki-xor> # if($a) { return not($b) } else { return $b } ^a^b``$a`<ki-not>$b$b = ^a``s``s`k$a<ki-not>i = ``s``s`ks``s``s`ksk`k<ki-not>`ki = ``s``s`ks``s``s`ksk`k``s``si`k`ki`kk`ki
まずは、一方向のみの条件分岐を考えてみましょう。
引数をB, T
の二つ受け取って、B
が真ならT
を返し、
B
が偽なら、v
を返すようにしましょう(ここがポイントです)。
すると、この関数はいとも簡単に、
^B^T`$B$T
と書けてしまいます。展開すると、
i
とまあ、えらく簡単に書けてしまいます。
さらに言えば、こんなものわざわざ関数化するまでもなくて、
真偽値B
に直接引数T
を与えてやれば済む話です。
論理演算の中で、これ(だけ)はとっても簡単です。
任意の二つの真偽値A, B
があったとき、
`AB
とやればandが実現できます。
その他の論理演算は、なかなか難関です。
一旦ki-bool値に変換した方が多分ずっと楽なので、
s
やk
, i
などを使っていろいろ考えてみますが……無理っぽいです。
どうやら、c
を使わないといかんともしがたい様です。
c
の使い方については、
リファレンスを参照していただくとして、
ここでは実際のコードを示します。
^b`c^x``k`ki``$b$xk = ^b`c``s`k`k`ki``s$b`kk = ``s`kc``s`k`s`k`k`ki``ss`k`kk
解説を試みてみます(解説するのはとても難しいです)。
まずは関数^x
の後半部分を見てみます。
``$b$xk
ここで$b
はv
かi
であり、
$x
はリファレンスで言う<cont>です。
もし$b
がv
なら、この部分はv
に評価されます。
もし$b
がi
なら、<cont>呼び出しが引数k
で発生し、
関数^b
がそのまま返り値k
で終了します。
^x``k `ki ``$b$xk
よって、この関数^x
は、
$b
がi
なら`ki
を返し、
$b
がv
なら<cont>呼び出しを引数k
で行います。
結果、関数^b
はvi-boolからki-boolへの変換を行うわけです。