今朝
ジョギングをしました。
自宅から、川沿いに岩手城公園までを往復で一時間近く走りました。
朝の六時は寒くて、とても気持ちいいです。もちろん朝からクタクタになっちゃいましたが。
トラックバックいただきました。
本ブログ開設以来、初めてアルファブロガーからトラックバックをもらいました。
そのアルファブロガーとは、id:rubycoの中の人です。
いやー、うれしい。大げさだけど、かれこれ2年もブログ続けてきてよかった。
トラックバックをもらった記事はこれ。
当ブログのタイトル「( (lambda(a)(a a))(lambda(a)(a a)))」について説明
あとついでに、これで、合ってると思います。
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~
- アーティスト: RHYMESTER,KICK THE CAN CREW feat.RHYMESTER,ラッパ我リヤ feat.RHYMESTER,GM YOSHI feat.RHYMESTER,DJ YUTAKA feat.RHYMESTER,K-DUB SHINE feat.RHYMESTER,SOUL SCREAM feat.RHYMESTER,忌野清志郎 feat.RHYMESTER,DJ HAZIME feat.RHYMESTER,WACK WACK RHYTHM BAND feat.Rhymester,SUPER 7
- 出版社/メーカー: ファイルレコード
- 発売日: 2007/02/23
- メディア: CD
- 購入: 1人 クリック: 28回
- この商品を含むブログ (9件) を見る
当ブログのタイトル「( (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の各コマンドの実装が自信ない・・。
ソースは以下です。