何やってるか分からなくて悔しかったので

lazy.cppを読んで、処理系の出力の扱いを見てみる。

main関数の最後んとこだけ

    e = Expr::partial_apply(e, new Expr(Expr::LazyRead));
    for (;;) {
        int ch = church2int(car(e->dup()));
        if (ch >= 256)
            return ch-256;
        putchar(ch);
        e = cdr(e);
    }

church integer(Lazyの内部でどういう扱いになってるのかは分からんが)を、我々の言う所のintに変換する。
putcharにかける。


という事は、hello -> Helloにしたいなら何らかの方法で頭のh(ascii 0x68)->H(ascii 0x48)にchurch integerでしてやれば良いんだな。
うんまぁ見る前と見た後じゃあ実感の違いがあるとかそんなもんを感じさせないぐらいコードは分からん。


言語によって書かれたコードより処理系の方が軽く読めるっていうのももうねw

まぁやるとしたら

Combinator-calculus styleだけ書ける処理系(simple Lazy_K)の実装かな。
その前に朝方(今も十分朝だけど)に注文したTo Mock a Mockigbirdとか読んでからにしてみたい(まじでLogical Combinatorとか謎)

Lazy_Kで入力のtailを取る。

とかそんなんを今日の朝方はやっていた。


Lazy_Kにおいてはinputとoutputは無限長のstream(まぁstream自体が無限の意味を内包している気がするので冗長?)として扱われて、更に言うとそれはpairのつながりによって表される。
ここでpairがどうなっているか、というと

(A . B)が
(lambda (f) (f A B))

という事になっている。勿論Lazy_Kにはlambdaなんてない(SKI combinator languageなのでS K Iのみ)のですけど。


さて、これを利用して標準入力を受け取りその一文字目以降を返す関数(というか式)を書いてみます。


ここで入力が"hoge"だとすると、先にならって(lambda (f) (f "h" "oge"))となっています。(ここでは取りあえず便宜上これで)
なので今回は

( (lambda (f) (f "h" "oge")) (lambda (a b) b))

が出来ると良いわけです。


さて、まず式をこの形に変形する為にSコンビネータ、Kコンビネータ、Iコンビネータのどれを使えば良いかを考えるのですが、ここではどう考えてもSコンビネータを使わざるを得ません。

取りあえず

S(I)([some])

としてあげれば、形としてはどうにかなりそうです。

([some])周りですが、Sはこれに入力を引数として適用します。が今回はここで入力をどうこうしたいわけでも無いので、取りあえず引数としては取るが棄却してやれば良いので、Kコンビネータを使いましょう。すると

S(I)(K([some]))

と出来ました。
後は[some]に相当する部分、つまり(lambda (a b) b)を書いてあげれば良いのですが、ここをどうやってやるかが要です。


引数を捨てるコンビネータはKコンビネータに他ならないのですが、Kコンビネータが捨てるのは第二引数です。こんかい捨てたいのは第一引数で、これをどうしてやるかが問題です。


欲しいものは

(K(?))という形をした関数で、引数として順にA,Bを渡した時にBを返す様なもの

です。

(K(?))ABは、((K(?))A)B

と適用される事を考えると、K(?)AがどうやらIを返せば良さそうです。という事は簡単に考えて?はIですね。


すると

(lambda (a b) a) -> (K)
(lambda (a b) b) -> (KI)

とこう成る事が分かります!!


ではここまでの生成物を組合せて

((lambda (f) (f "h" "oge"))(lambda (a b) b)) => "oge"
↓SKIコンビネータで書く
SI(K(KI))

なんとか出来ました。


理論的な事云々は何も書きませんでしたが、なんとか普通の事も出来るもんだなと・・・。
ただHole2を書く為にはまだ色々足りない部分がありますねー。Boolean logicとかとか。

Lazy_Kの次

取りあえずconsを書いてみた
やる事は、toUpperする為に10進+32をしたいわけだけど、church integerとかでコード書かねば成らん。


で、0,1,2..だののリテラルを直書きするのはなんとかなるのかもしれないけど、そんなの正気の沙汰じゃないし大体そんなのでどうやって書けっちゅーねんという話なので何とかして加算をする必要がある。


後やる事はループか再帰、それとifだなー。spaceを扱うのはどっちみちやらないといけないだろうし・・・。
S,K,I全てのコンビネータは与えられているんだから後はテクニック次第なんだろうけどねwww
自分で考えたらどうにかなる、と言われれば流石になる言語だけどFactor調べたりであんまし時間ねーなー。