プログラミングGauche

コルーチン3(コルーチンから脱出)

プログラミングGaucheのpp298-303。前回のコルーチンによるREPLは(exit)を与えてGaucheのインタプリタを終わらせるまで無限に繰り返していたけど、今回はコルーチンから脱出してGaucheのREPLのトップレベルに戻ってくるように修正するらしい。そのために定義…

コルーチン2(call/ccでREPL)

プログラミングGaucheのpp296-298。今回はコルーチンでREPLを実装する。もちろんread、eval、printの各処理はGaucheに丸投げだけどな!それは実装とは言わないッ! 実行結果がこんな感じになるように、3つのコルーチンreader、evaluator、printerを作成する…

コルーチンをC#で

前回のコルーチンっぽいものをC#で書いてみた。いろいろ問題があるかもしれないけど。 無限ループなので、Ctrl+Cかなんかで中断すべし。 /// <summary>The class which represent the co-routines which should be work cooperatively.</summary> /// <typeparam name="T">The type of return value </typeparam>…

コルーチン

プログラミングGaucheのpp.294-296の「コルーチン」の前半。 call/ccでコルーチンまで実現できるらしい。ってことで、コルーチンを実現するための構文define-coroutineの定義を写経。 ;; キューの機能を使うから (use util.queue) ;; コルーチン再開するとき…

簡易な例外機構

プログラミングGaucheのpp.292-293。他の主要な言語でいうところの例外みたいな仕組みすらcall/ccで実現可能らしい。 そういえば組込みのguardもcall/ccで実装されていると聞いたことがあるな。 call/ccどんだけー。 目標とするクライアントコードは次のとお…

break/next名前付きfor-each

他の主要な手続き型言語でいうところのbreakやcontinueの仕組みを、Schemeの組込みのfor-eachに追加してやろう、ということらしい。 つまり、次のようなことができるようにしたい。 gosh> (for-each-ext return next (lambda (x) (cond ((odd? x) (next #t))…

大域脱出

call/ccを利用した大域脱出の例。今までcall/ccでウダウダ考えていたのでさすがに挙動の理解は簡単。 ただし、継続と絡めて説明しろと言われても無理。そういう意味ではcall/ccは全く理解できていない。指定したラベルを含むS式から脱出するマクロblockを定…

call/cc理解不能

19.4のcall/cc、全くわからん。何もかもが分からん。 「call/ccで継続を取得できるよ」って言ってるだけのような気がして、 なぜあのコードでfind-foldが正しく動くのか call/ccで取得した継続って具体的に何なのか なぜあそこでcall/ccするのか などなど、…

さらに継続を渡して

find-foldからfind-fold2にすることで、procを継続渡し方式に変更できた。 だけど、find-fold2自身は(null? lis)が真となるときに、依然として「seed(=戻り値)を返却する」というCall-Return方式になっている。 これを継続渡し方式に修正してみよう、との…

継続渡し形式

find-foldからfind-fold2への書き換えでいきなりつまずいてたけど、やっと理解できてきたかも。 指定した条件を満たす要素だけfoldするfind-foldは、素直に書くと以下のようになる。 (define find-fold (lambda (pred? proc seed lis) (cond ((null? lis) se…

継続渡しで実行を制御する

find-foldで済むものを、なぜ手間をかけてfind-fold2にするのか。 それは外から与えられるproc/contを少しいじるだけで、find-fold2の実行を制御できるからだ、と。 ということで、コード例をば。次のようなnextとbreakとadd/breakを定義して、 (define next…

新たな変数名の作成

id:yagiey:20100305:1267761841にトラバもらった。id:trotr:20100308:1268043643 引数を加工することが必要っぽいので、objectを書き直してみた。 今度はちゃんとget-○○○って名前にした。 (define-macro (object args . methods) `(lambda ,args (lambda (mn…

むずい...

やっと継続の章に入った。find-foldの継続渡し形式への変換でいきなりつまづいた。 今までもそうだったけど、読んですぐ理解できないことなんていくつもあった。 今回も、何日もかければきっと理解できるはず! 1章3節「Scheme」(6ページ)で lambda式は、…

使い捨てのシンボル

適当なシンボルを生成したいときは、シンボルを生成してくれる手続きgensymを使えばいい。 gosh> (gensym) #:G1 とまあ、こんな感じ。 このgensymと伝統的なマクロを使って、id:yagiey:20100127:1264595558で定義したmy-orを書き直してみると (define-macro …

objectマクロを非R5RSマクロで

今回は勝手にシンボルをでっちあげて、新しい名前を作ってみる。 271ページの 例えば構造体を定義するマクロdefine-structを定義することを考えます。fileという構造体を定義し、それがnameというスロットを持つ場合、自動的にfile-nameというスロットアクセ…

新たな変数名の作成

id:yagiey:20100213:1266088272で 「新たな変数名を作り出す」という要請に対しての解決策という形で紹介される伝統的なマクロ とか言ったけど、 (define-macro (make-foo) 'foo) でも、立派に新しい名前を作ってると言えるよね。ただ、外側でfooが束縛され…

やっと分かった

ずっと (define-macro (my-when test . body) `(if ,test (begin . ,body))) が理解できなかった。具体的に言うと、 (my-when (even? 4) 1 2 3 4) って使うと、,testが#tになると思い込んでいたので、,bodyが(1 2 3 4 5)という関数適用でエラーにならないこ…

R5RSマクロの限界

Schemeのマクロには大きく分けて R5RSマクロ:パターンマッチによるマクロ レガシーなマクロ:LISPに伝統的なマクロ があるとid:yagiey:20100126:1264525307で紹介した。 今回は後者に関して。 R5RSマクロは以下のようなマクロを実現できない、もしくは実現…

マクロの使用例

マクロ定義の実例として、簡単なオブジェクトシステムを書くことを想定したケースが紹介されている。ここで登場するオブジェクトは、以下のような銀行口座を表すオブジェクト。(以下のC#コードは動作確認してません) using Sysmtem; public class Account …

マクロをいつ使うか

letはlambdaによる無名関数の適用へと展開される(id:yagiey:20100128:1264705405)。 だからletは(仕様が要求するけど)必須構文ではない。 だけどletによって「ローカル変数」という概念ができる。 このように、 そのマクロによってまとまった、明確な抽…

マクロの健全性

id:yagiey:20100127:1264595558のorマクロを使って次のようなコードを書いたとする。 (let ((tmp 2)) (or #f tmp)) orを素直に展開すると (let ((tmp 2)) (let ((tmp #f)) (if tmp tmp tmp))) ってなって、展開前に意図した結果が得られない。困った。 さら…

R5RSマクロその2

R5RSマクロは、 式の構造のパターンマッチ マッチした時に展開されるテンプレート という形で定義されるってのはこの前やった。 しかし、式の構造だけではなく、同じ字句かどうかで判定しなければならないことがある。それがcondで、なぜならelseという字句…

let

マクロの練習に、自分でletを定義してみた。 (define-syntax my-let (syntax-rules () ((my-let ((var init) ...) expr ...) ((lambda (var ...) (begin expr ...)) init ...)) ((my-let fname ((var init) ...) expr ...) (my-let ((fname #f)) (set! fname…

R5RSマクロその1

R5RSマクロはパターンマッチの仕組みを利用して、式の変換規則を定義する。 こんな感じ。 (define-syntax マクロ名 (syntax-rules () (パターン1 テンプレート1) (パターン2 テンプレート2) ;; 中略... (パターンn テンプレートn))) パターン1、パターン2と…

構文の拡張

やっとここまで来たなぁ。18章は「構文の拡張」。 ...って、12〜17章はすっ飛ばした。悪しからず。いつか読む。 とにかく18章と19章が早く読みたかったし、特に飛ばしても差し支えなさそうだったし。 さて、18章はLISPをLISPたらしめると言われている(どこ…

気になったので実験してみた

useしたものは、局所環境フレームに束縛が追加されるのかな? gosh> (begin ((lambda () (begin (use srfi-1) #t))) (iota 10 1)) (1 2 3 4 5 6 7 8 9 10) あれ?iotaされてしまった。 Gaucheのドキュメント読まないと分からんなぁ。

ポップされた環境フレーム

前のエントリで、ポップされた環境フレームに関する疑問をちょっと書いた。 で、それっぽい答えを出したけど、その答えが正しいとしたら、また新たな疑問がでてくる。 例えば、次の条件を全て満たすような場合はどうするんだろう。 環境からポップされた環境…

環境フレームモデル

置き換えモデルではbeginやset!が絡んだ時に正しい値にならなかった。だけど、環境フレームモデルでは正しく計算できるらしい。 だい〜ぶお利口、置き換えモデルよりいくらかCOOL(by 宮崎吐夢 環境フレームモデルでも「環境」を用いるが、置き換えモデルの…

あれれ?

The Little Schemerの10章でなんちゃってevalを作っていたので、環境フレームモデルは理解しやすかった...ような気が一瞬した。 だけどエントリを書こうと頭を整理していたら、あんまり分かってなかったことに気づいた。また、何が分からないかも分からない…

作用順序評価

2つの評価モデルの話に進む前に、作用順序評価という概念について少し。 id:yagiey:20100103:1262535864の最後らへんで書いた内容に関係するような気がするなぁ。 Schemeでリストを式として評価する時は基本的に関数適用になるけど、この関数適用に先立って…