トラックバックいただきました。

本ブログ開設以来、初めてアルファブロガーからトラックバックをもらいました。
そのアルファブロガーとは、id:rubycoの中の人です。
いやー、うれしい。大げさだけど、かれこれ2年もブログ続けてきてよかった。


トラックバックをもらった記事はこれ。

当ブログのタイトル「( (lambda(a)(a a))(lambda(a)(a a)))」について説明


トラックバックの記事はこれ。
lambda


あとついでに、これで、合ってると思います。

lambda {
  |a| a.call(a)
}.call(lambda {
  |a| a.call(a)
})

でも、|a|は "{"や"do"と同じ行に(私は)書きますね。rubycoさんの書き方はSmalltalkに似てるんでしたっけ?
どうでもいいことですが。

Befunge

Wikipediaで見つけた、二次元すごろくプログラミング言語。言語使用を読んだら、思ったよりシンプルだったので作ってみました。
この言語、非常に面白いです。

無限ループ

左上から始まり、右向きに移動して、「<」に来ると、左向きに進みます。
左端に到達すると、今度は右から出てきて、「^」に到達します。
今度は上に進み、「>」→「v」→「<」→「^」→「>」→「v」→「<」→「^」って、無限にループします。

<^
v>

Hello World!を表示

さっきより複雑です。
コマンドの詳細はWikipediaを参照してください。Befunge
矢印の順番に進んで、Hに到達した時点でスタックには、[数値の0,!,d,l,r,o,W,<スペース>,o,l,l,e,H]、このようにデータが積まれてています。その後、スタックの0が出てくるまで、ループして一文字ずつ出力して終了します。

v @_       v
>0"!dlroW"v
v  :#     <
>" ,olleH" v
   ^       <

インタプリタソースコードは以下です。
こんな感じで実行すれば動きます。-dオプションをつけると、いろいろ表示されるかも。

ruby befunge.rb {Befungeのソースファイル}
続きを読む

CD買いました

客演もいいねー。

ベストバウト~16 ROUNDS FEATURING RHYMESTER~

ベストバウト~16 ROUNDS FEATURING RHYMESTER~

当ブログのタイトル「( (lambda(a)(a a))(lambda(a)(a a)))」について説明

まずS式について

「1 + 2」を「(+ 1 2)」と表現する書き方があります。

1 + 2 - 3 * 4

(- (+ 1 2) (* 3 4))

となります。これがS式です。

高階関数

関数を値として扱います。


自分で関数を定義する時、高校とかだと以下のように書くと思います。

f(x) = 2 * x + 1
関数f(x)は、xに2をかけて、それに1を足します。


練習にf(10)を解きます。

f(10) = 2 * x + 1
      = 21


f(x)をちょっと変形します。

f = {x => 2 * x + 1}
fは、xを引数にとって、xに2をかけてそれに1を足す関数です。


さらに、「f = {x => 2 * x + 1}」をS式の流儀チックに変形するとこうなります。
lambdaは関数を作るって意味です。

f = (lambda (x) (+ (* 2 x) 1))
(f 10)
  = (+ (* 2 10) 1)
  = (+ 20 1)
  = 21

では「( (lambda(a)(a a))(lambda(a)(a a)))」は?

さて、ようやく本命の「( (lambda(a)(a a))(lambda(a)(a a)))」という式に入ります。
この式は以下のような感じに分解できます。

A = (lambda(a)(a a))
B = (lambda(a)(a a))
(A B)

つまり、こうなります。

A = {a => a(a)}
B = {a => a(a)}
A(B)

さらに噛み砕くとこうなります。

A(a) = a(a)
B(a) = a(a)
A(B)

後は、実際に計算してみます。

A(B) = B(B)             A(a) = a(a)より、
     = B(B(B))          B(a) = a(a)より、
     = B(B(B(B)))       B(a) = a(a)より、
     = B(B(B(B(B))))    B(a) = a(a)より、
     = ....

無限に計算が終わらないことがわかります。


つまりこの「( (lambda(a)(a a))(lambda(a)(a a)))」という式は、永遠に答えが出ない式なんです。

答えがないという答え

「幸せとは何か?」とか「人生とは何か?」とかめんどくせーから、答え無しという答えでズルしようぜ、みたいな。
無限に広がる話を、尻すぼみに終わらせてみた。

Whitespaceのスタックマシン作成

Schemeの継続の実装について、いろいろマクロとかevalとかに悩んでで停滞してるので、
今度はWhitespaceに手を出してみました。
俺のニセSchemeいづれはスタックマシンライクなバーチャルマシンで動かすつもりなので、その実験台として、Whitespaceのインタプリタ作成です。

Whitespaceは、スペース(' '), タブ('\t'), 改行('\n')だけで記述されるプログラミング言語で、印刷しても全く読めないため、スパイなどに向いているのだそうです。(Whitespace http://ja.wikipedia.org/wiki/Whitespace)

今回出来たのはスタックマシンのみです。まだWhitespaceのコードを解釈できるようにはなっていません。アセンブリ言語のような中間言語を実行できるだけです。

下記ソースをws.jsとして保存して、コマンドプロンプトから"cscript ws.js"と入力すれば実行できます。ずらーっとログが出たあと、フィボナッチ数列の10番目の値、55がスタックに残っているのが分かるんじゃないかと思います。

作って分かったこと

CPS変換ってのは、スタックマシン用のバイトコードコンパイルできれば、十分なんじゃないかと思う。
あと、バイトコードに変換すると、末尾再帰の判定が簡単に出来そうな気がしてきた。つまり、関数内で自分と同じ関数が呼ばれた(再帰した)後、putLabel, jmpだけを通過してretに到達できていれば、末尾再帰なんだと思う。そしてその時は、再帰する場所で、実際に関数を呼び出すのではなく、今の関数の先頭にジャンプさせるっと・・・。

疑問点

store,retrieve,slide,readNumの各コマンドの実装が自信ない・・。


ソースは以下です。

続きを読む

Unlambdaインタプリタ by Ruby

Schemeインタプリタに行き詰まってきたので、とりあえず超難解プログラミング言語、Unlambdaのインタプリタを作っちゃいました。
http://hw001.gate01.com/eggplant/tcf/unlambda/

たぶん、それなりに動くものが出来たと思います。
まあ、俺自身Unlambdaのプログラムが書けないのに、ちゃんと動くっぽいってのも変だけど。
そういや、Rubyでプログラム書いたの久しぶりかもしれないな。


次はWhitespaceのインタプリタを作ろう!

続きを読む