Scheme

名前付きlet、ふたたび。

名前付きletがなかなか腑に落ちないので、名前付きlet使って階乗計算(ローカル手続きで末尾再帰)やってみた。 gosh> (use srfi-1) #<undef> gosh> (define fact-named-let (lambda (n) (let f ((m n) (cont (lambda (_) _))) (if (= m 0) (cont 1) (f (- m 1) (la</undef>…

matchでのエラー処理

はい、まだまだ9章5節。 依然としてmake-playerは奇数個の引数を受け付けない。 「奇数個の引数に適用することを受け付けない」というのは無理だけど、せめてもう少しわかりやすいエラーメッセージを出したい。 ということで、matchで全てのパターンにマッチ…

名前付きlet

9章5節。名前つきlet。 今回はRPGを想定して、以下のようなプレイヤーの状態をを表す連想リストを規定してみる。 ((hp . 320) ; 体力 (mp . 66) ; 魔力 (position . #f) ; 現在位置 (inventory potion potion dagger cookie dagger) ; 持ち物 ) 「ポーション…

連想リストふたたび、ふたたび2

めっちゃ嘘ついてた。 ってか、それ以前に、has-item?(id:yagiey:20090307:1236410294)とdelete-item!(id:yagiey:20090307:1236410958)は使っちゃダメだよね。 だって*inventory*から消してしまうし。 連想リストふたたび、ふたたび 違ぁぁぁーう!! どう…

連想リストふたたび、ふたたび

まだ9章4節。 id:yagiey:20090310:1236690209のデータベースから、値を取り出すための手続きを作ってみる。 (define item-properties (lambda (item) (cond ((assoc item *item-database*) => cdr) (else '())))) (define item-property-get (lambda (action…

連想リストふたたび

9章4節。 連想リストをネストさせて簡易データベースを作ろう、と。 データベースとは、 データベース = ((アイテム1 . アイテム1の性質) (アイテム2 . アイテム2の性質) ・・・ (アイテムn . アイテムnの性質)) アイテムの性質 = ((属性1 . 値) (属性2 . 値…

手続きによるパターンの抽象化

9章3節。 id:yagiey:20090309:1236597268の最後で挙げた3つの手続きは、以下の共通部分を持つ。 (lambda (elt lis . optionals) (let-optionals* optionals ((cmp-fn equal?)) (define loop (lmabda (lis) (cond ((null? lis) ○○) ((cmp-fn elt (△△ lis)) (□…

連想リスト

9章2節、連想リスト。 キーと値のペアで保存しといて、キーを元に値にアクセスするアレ。 多くのスクリプト言語などにも、連想配列という形で実現されてたりするな。 Schemeではキーと値のペアをドット対で表現し、連想リストをドット対のリストとして表現す…

サポートページ

プログラミングGaucheのサポートページに模範解答があるじゃないっすか! delete-1の解答をみてみると、結構違うじゃーん。 >< 模範解答 (define (delete-1 elt lis . options) (let-optionals* options ((cmp-fn equal?)) (define (loop lis) (cond [(nul…

set!

既に束縛されている名前を、再び違うオブジェクトに束縛する手続き。 多くの手続き型言語でいう「代入」をやりたいときに使う。 gosh> (set! lambda 3.141592) 3.141592 gosh> lambda 3.141592 みたいな。 これやっちゃうと大変なことになるけどね! で、指…

9章1節の練習問題:delete-1

srfi-1のdeleteは等価述語を満たす要素を全部削除してしまうけど、見つけた1つ目だけ消す手続きdelete-1を定義してみると (define delete-1 (lambda (elt lis . optional) (let-optionals* optional ((cmp-fn equal?)) (define loop (lambda (lis) (cond ((n…

delete

gosh> (use srfi-1) #<undef> gosh> (define *p* (cons 1 2)) *p* gosh> (delete *p* (list *p* *p* (cons 1 2) *p* *p*)) () gosh> (delete *p* (list *p* *p* (cons 1 2) *p* *p*) eq?) ((1 . 2)) みたいな、第1引数を第2引数のリストから見つけて全部削除した残</undef>…

member

gosh> (member 'cookie *inventory*) (cokkie dagger) gosh> (member 'ration *inventory*) #f のように、第1引数を第2引数の中から探し、見つかった場合には見つけたものを含めた残りのリストを、見つからなかったら#fを返す。 つまり、ifなどの条件式に使…

9章はじめー

9章1節、集合。 うっはー! 代入が一般的ではないSchemeで、どうやって状態を扱うのかとても興味がある。 すべて式である なんて言っちゃってるけど、やっぱ代入しちゃうのね。 新出の手続きは以下。 member set! delete これらの手続きを使って、持ち物を表…

and-let*

8章4節、and-let*に関して。 条件式が#fじゃなければその値を使って計算して、その結果で真偽を判定して、#fならば処理を止め、#f以外ならばさらにその値を使って計算して...、みたいな場合、つまり int val1=0,val2=0,val3=0; if ((0 != (val1 = SomeFunc1(…

whenとunless

8章4節のwhenとunlessに関して。 when 与えた式が真となるとき(つまり#fにならないとき)に限り処理をする場合に使う。 (when <条件式> 複数のS式) を評価した後、それが#f以外になれば以降に続く「複数のS式」を順に評価して、最後のS式の値をwhen全体の値…

andとor

8章4節のandとorに関して。 and 複数の引数を取り、先頭から評価していって、#fを見つけたら直ちに評価を中止し#fを返す。 引数が全て#f以外の値だったら、最後に評価した値を返す。 gosh> (and 1 2 3 #f 4 5) #f gosh> (and 1 2 3 4 5) 5 簡単。 or 複数の…

case

8章4節のcaseに関して。 C言語とかでのswitch-case文みたいなことができるのね。 (case <key式> (リスト1 複数のS式) (リスト2 複数のS式) ... (リストn 複数のS式) (else 複数のS式) まずを評価する。 んで、リスト1、リスト2、...、リストnの順に要素にと同じもの</key式>…

すべて式である

106ページからのコラム「すべて式である」。 今までSchemeをやってきて、このコラムが言いたいことは大体理解できた。 だけど、評価結果が未定義の場合はどうするのだろう。 Schemeでの未定義な値は、Gaucheでは#らしいけど、この値を使って何かを計算するの…

仕様

どこまでがSchemeの仕様で、どこからがGaucheの拡張なのかなぁ。 この本を読んでいて、よく思う。 初心者のうちはそこまで気にする必要はないのかも知れないけど。 Schemeの仕様について知りたければ、R5RS(http://www.unixuser.org/~euske/doc/r5rs-ja/)…

cond

8章4節のcondについて。 条件判断といえば、自分はif式よりもこっちばっかり使ってるな。 たぶんThe Little Schemerのせい。 condも知らないことが結構あった。 (cond (条件式1 条件式1が#f以外の値になった場合のcond式の値) (条件式2 条件式2が#f以外の値…

if

8章4節のifについて。 今まで何度か使ったけど、知らないことも多かった。 (if 条件式 条件式が#f以外の場合のif式の値 条件式が#fの場合のif式の値) だそうだ。 3つ目の引数は省略可能だということは初めて知った。 3つ目の引数が省略された場合に「条件式…

8章3節の練習問題とか

any-predとevery-predを自分で定義しなさい、ということなので、やってみた。 (define my-any-pred (lambda args (lambda (x) (cond ((null? args) #f) (((car args) x) #t) (else ((apply my-any-pred (cdr args)) x)))))) (define my-every-pred (lambda a…

もうちょっと述語

8章3節、真偽値に関する手続き。 等価述語以外の述語 前回は等価述語だったけど、等価述語以外にも述語はたくさんありますよ、と。 型を判定したり、値の性質を判定したり。 詳しくは追々出てくるっぽい。Schemeには述語を引数にとったり、述語を返したりす…

いろいろな「等しさ」

さて、8章2節。 真偽値を返す関数のことを「述語」と呼び、とくに等しいかどうかを調べる関数を「等価述語」と呼ぶ。 C++のSTLや.NET Fremeworkでも出てくる用語なので、一応知ってた。 英語でいうとpredicateね。 ...はい。で、本題。 「値が等しい」と一口…

キーワードって何ぞ?

そういえば、キーワード引数のところ(82ページ)で、 キーワードは :名前 と、コロンの後に名前を書くことで作成できます。 とあった。 「作成できます」って書いてあるから、なにかが定義されるのかと思ったけど、そうではないみたい? 'hoge が (quote ho…

Lisp脳

大いに感動した。 手続的な発想では、毎回特殊な処理を行いそれを繰り返すという発想でプログラミングしていました。 Schemeプログラマはそうは考えません。 「データからデータへの変換を考えれば良く、出力は後からどうにでもなる」 と考えています。 「Li…

多値

これまた今までの文化に無いので、メリットが実感できない概念。 理解すんのは難しくなさそうだけどね。

部分適用

cutという構文を使うと (lambda (a) (func a x)) を (cut func <> x) って書けるそうだ。<>が引数になるような関数が作れる。 (cut func <> x) のcutを取っ払って (func <> x) にして、 さらに <> を引数にして (lambda (a) (func a x)) の出来上がり。 なん…

キーワード引数

引数に関数を適用する際に、引数に名前みたいなもの(= キーワード)をつけられる。 そのおかげで、引数の順番を覚えておかなくてもよくなるらしい。引数が多い場合に便利そう? この概念は始めて出会うなぁ。スクリプト言語にはあったりするのかな。 ってこ…