ディジタル回路のシミュレータ

SICP3章にあるディジタル回路シミュレータの話。基本情報以来、数年ぶりに見た半加算器を事象駆動シミュレーションで実装してみる。半加算器のようなプログラムは、単純な要素を相互接続して構成する。一つ一つの要素は簡単だが、それらをネットワークとして繋げてみると非常に複雑に振る舞うことができる。「事象駆動」という言葉が見慣れないが、SICPでは下記のように記載されている。

事象駆動では、行為(「事象」)は後続の時刻に発生する先方の事象を惹き起こし、それが更に多くの別の事象を惹き起こすふうに続く.

ディジタル回路のシミュレータでは、いくつかの簡単な機能箱を作成する。それらを回線(wire)で結びつけることにより、インプットとなる信号は変化して出力される。機能箱はたとえば、論理和や論理積というような基本的機能を用いる。また、回路を形成する際に必要な機能として、遅延時間を組み込む。一つ一つの機能箱に遅延時間を組み込み、遅延時間後に与えられた手続きを実行することとする。


ここで問題3.31を解く。

make-wireで定義した内部手続きaccept-action-procedure!は、新しいアクション手続きが回線に追加されると、この手続きを直ちに走らせるように規定する. この初期化が必要な理由を説明せよ. 特に上の段落での半加算器の例をトレースし、accept-action-procedure!を
(define (accept-action-procedure! proc)
 (set! action-procedures (cons proc action-procedures)))
のように定義したら、システムの応答はどう違うかを述べよ.

この問題、ちゃんとトレースしないとなかなか頭の中で納得が得られなかった。おそらくまだ、関数型言語に頭が慣れていないからだろう。関数から関数へ渡される時に見失うことが多い。とはいえ、きちんとトレースすれば「そういうことかぁ、なるほどね!」と納得感がある。

この問の答えは、procedureの実行を行わないと、各機能箱の中にあるafter-delayが実行されず、実行計画を管理しているagendaにactionが登録されないために、逐次実行する必要がある、ということになる。つまり、propagateが取り出すagendaの中身は、各機能箱によって変化した値を代入によって更新する処理であり、それらを取り出す際にlambda内の代入処理が実行される、ということになる。

個人的に引っかかったというか、気持ち悪いな、と思ったところは、各機能箱の中にあるafter-delayが、agendaへの登録機能を担っている、というところ。後々になって、まぁわかるけど、、とはなったが、関数名的にはagendaへの登録がすぐに紐付かないのでイマイチだなぁと思ってしまった。

いやまぁ気持ちはわかるけど。

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.