SICP5章 schemeでレジスタ計算機を模倣する

ずっと5章に興味が持てなくてほったらかしにしていたのだけど、読み始めた。5章は毛色が違うように感じてたのと、単に関数型言語が知りたいだけだったら3章までで満足できて、計算機の話って何が面白いんだろうか?なんて思ってたのだけど、(僕の場合)以下のような道のりを経て5章にたどり着いた。

EsoteicでVMとかエミュレータみたいなもんに興味がわいた。あと中間言語

Bolicとか。そういえばゲノム言語とかつくったみたな。

ProductName Rubyで作る奇妙なプログラミング言語 ~Esoteric Language~
原 悠
毎日コミュニケーションズ / ¥ 2,814 ()


プログラミングの力を生み出す本

Cのプログラムをアセンブリから眺めてみる。レジスタとかメモリとか意識できるようになった。

ProductName プログラミングの力を生み出す本―インテルCPUのGNUユーザへ
橋本 洋志,松永 俊雄,冨永 和人,石井 千春
オーム社 / ¥ 2,625 ()


CPUの創りかた

4bitCPUつくる。半加算器とか全加算器が論理回路でつくれるとかそういう話は楽しい。

ProductName CPUの創りかた
渡波 郁
毎日コミュニケーションズ / ¥ 2,940 ()
在庫あり。

SICP5章

という長い道のりを経て、やっとSICP5章。

ProductName 計算機プログラムの構造と解釈
ジェラルド・ジェイ サスマン,ジュリー サスマン,ハロルド エイブルソン
ピアソンエデュケーション / ¥ 4,830 ()
在庫あり。

数日かけてバグとって、実際にGCDマシンが動いた時にはかなり感動。

gosh> (set-register-contents! gcd-machine 'a 206)
done
gosh> (set-register-contents! gcd-machine 'b 40)
done
gosh> (start gcd-machine)
done
gosh> (get-register-contents gcd-machine 'a)
2

デバッグしながら中身の動きが理解できた。

GimpのScript-Fu

Script-Fuコンソールを起動するとScheme処理系が立ち上がる

tinyscheme

なにか書いてみたくなりますな。

プログラミングGauche読了

やっと読み終わった。

ProductName プログラミングGauche
Kahuaプロジェクト
オライリージャパン / ¥ 3,360 ()
通常24時間以内に発送

19章の継続のところのcall/cc、コルーチンの話と、26章の自前で簡易HTTPサーバーを作るところが面白かった。

また、(SICPと違って)文字列処理とかモジュールの話などの実用性に重きをおいた部分がよくまとまってperlのように使える気にさせられる。

perlからruby,pythonに移ったって話は聞くけど、perl,ruby,pythonからgaucheに移ったっていうヒトはいるんだろうか?

pythonのスコープではまる

ちょっとはまった。結局オブジェクト作って解決しといたけど気持ち悪いので少し調べた。(でも未解決)

クロージャでカウンタを考える。Open Source WEBを参考に

perlだと

sub make_counter {
  my $c = $_[0] || 0;
  return sub { $c++ }
}

gaucheだとこんな感じ

(define (make-counter n)
  (let1 c n
    (lambda () (inc! c))))

でもpythonだとだめなの

def make_counter(n):
    c = n
    def counter():
        c = c + 1
        return c
    return counter

スコープの洗礼をうけた。参照できても代入できないのでglobalにする必要が。

def make_counter(n):
    c = n
    def counter():
        global c
        c += 1
        return c
    return counter

ctr = make_counter(5)
ctr()
ctr()

Traceback (most recent call last):
  File "C:\home\kzfm\test.py", line 10, in <module>
    ctr()
  File "C:\home\kzfm\test.py", line 5, in counter
    c += 1
NameError: global name 'c' is not defined

とかいってglobalでも駄目だ。

Gaucheのbeginはperlのdo

最後の式を評価して返す

Gaucheの引数

GaucheはなにやらPerlとかPythonっぽくて楽しいですな。毎日Gaucheクックブックを一つは読むようにしてわからないとこを調べながらというスタイルで。(まだ3日だけど日付順に読んでる)

3.3 Schemeスクリプトを書く

いくつか簡単な例を示します。最初の例はUnixのcat(1)コマンドを模するものです。エラー処理やコマンドラインオプションの処理は行っていません。

#!/usr/bin/env gosh

(define (main args)   ;entry point
  (if (null? (cdr args))
...

(cdr args)ってことはperlの$0みたいに(car args)もプログラム自身の名前を返すのかも。

(define (main args)
(print "car:\t" (car args))
(print "pname:\t" *program-name*))

program-nameはスクリプトファイル名に束縛されるらしい。

$gosh test.scm
car:    test.scm
pname:  test.scm

Gaucheのlet1

let1って何だろうって思ったので。

Gauche ユーザリファレンス: 4.6 変数束縛

let1 var expr body …

変数が一つしか無い場合の便利なマクロです。次のように展開されます。

(let ((var expr)) body …)

Scheme入門読んだ

1章から12章まで割と一気目で。

以下覚書

シンボルの大文字と小文字

Gauche ユーザリファレンス: 2.4 大文字小文字の区別

Lisp系の言語は歴史的にシンボルの大文字小文字を区別していませんでした。 Schemeもその流れを汲んでおり、R5RSでもシンボルは読み込まれる時に大文字小文字の区別をしないと定義されています。(但し、R5RSの範囲内でも処理系内部では大文字小文字を区別することになってます。ここで問題としているのは読み込み時の動作です。)

しかし現在では、プログラミングが一つの言語で完結することは滅多にありません。他の言語とインタフェースを取る場合、Scheme側でも大文字小文字を区別するようにしておいた方が便利です。

gosh -fcase-fold

で大文字小文字を区別しないモード

cdrの読み

クダー

カー、シーディーアールって読んでた。

let系の違い

Scheme入門 第12章 局所変数レット

局所変数(ローカル変数)を定義する let, let*, letrec という構文もあります

letrecをいまいち理解しないでSICP読んでた。

日本語

コンパイル済Windows用バイナリだと日本語が化けたがどうすればいいのかちょっと見つからなかった。

gosh> (gauche-character-encoding)
utf-8

内部文字エンコーディングはUTF-8

クックブック

Gaucheクックブックを一日ひとつ見ていけば3ヶ月以上楽しめてナイス。

相変わらず継続

継続のあたりをうろうろしてますが、先週末に到着したOn Lispの継続の章をつまみ読みしてまたちょっと理解がすすんだような気がしたようなしないような。

ProductName On Lisp
ポール グレアム,野田 開
オーム社 / ¥ 3,990 ()
通常24時間以内に発送

最後の方で、

継続

CPS変換を覚えればcall/ccを書くのは簡単だ. CPS変換を経たプログラムでは,全体に対する現在の継続が常に存在し, call/ccはその引数として何らかの関数を呼び出す単純なマクロとして実装できる.

と書いてあるのだが、perl - to goto or not to goto, that's the continuationの先にどうやればperlでcall/ccが実装できるのかわからん。

rubyにはcall/ccがあるらしいですね

そもそもCall/CCがrubyに実装されている理由はただ一つで、「実装できてしまったから」である。