ラベル TheSeasonedSchemer の投稿を表示しています。 すべての投稿を表示
ラベル TheSeasonedSchemer の投稿を表示しています。 すべての投稿を表示

2011年9月17日土曜日

Scheme修行15章



Scheme修行は毎章違う題材が出てきます。前の章の継続も面白かったけど今回のも面白い。


メモ等




  • ここに来て初めてdefineで値に名前をつける。

  • set!の読み方「セット、バン!」

  • set!は値を返さない。defineと似たもの。Lispではsetq(セットキュー、説得)

  • set!すると名前の参照を変更出来る。あたかもxが定義されてないときにdefineで名前をつけるように。

  • lambdaの値部分に2つ式があるのはletやbeginと同じ。2番目の式(最後の式)の値を返す。

  • 別々の関数で同じ名前に対してset!する衝突が起こりえる。それは困る。

  • lambdaをletで囲む


    • あたかも架空の名前x1をdefineしたかのよう

    • 架空の名前の値はない。

    • 架空の名前が何を表しているか覚えておかないといけない



  • 16の戒律「(let...)で定義された名前に対してのみ、(set!...)を使うべし


    • 大域的な名前にset!すると駄目



  • 第17の戒律(予備版)


(let ( (x ...)) ...)に対して(set! x ...)を用いる際には


それらの間には少なくとも1つのlambdaを置くべし




  • letとsetの間にlambdaを入れないで使っても何かを覚える役には経たない

  • 第18の戒律「(set! x ...)はxが参照する値がもはや必要ないときにのみ使うべし」


    • set!すると値への参照がなくなってしまうので。

    • swapを例に

    • letを使って名前をつけるとその値を参照するのに2通りの方法がある




感想


15章ではset!の使い方と破壊的代入の問題点を説明している感じがしました。


ふつーのプログラミング入門だと変数に値を入れるのが関数の定義よりも先に来ますよね。


Scheme手習い、Scheme修行ではアトムから始まって、すぐに関数を定義して、値は引数で取り、関数を組み合わせて抽象化し、わざわざ関数に名前をつけずともY Combinaterがあれば再帰が出来る事を示し、計算結果を覚えるためにletを使い、と、ここまで値にdefineで名前をつける必要がありませんでした。


set!の説明と問題点を示すためだけにdefineで値に名前をつけている気がします。


関数プログラミング的な考えが重用視されてるような感じをちょっと受けています。


次の章が楽しみです。set!の上手い使いどころを示してくれそうな感じ。


# ホワイトボード使ってやるのも楽しそうですね


※ところでこの章、試験なナニを書けない気がします。なので実行ログを残しました。



gosh> (define x
(cons 'chicago
(cons 'pizza '())))
x
gosh> x
(chicago pizza)
gosh> (set! x 'gone)
gone
gosh> x
gone
gosh> (set! x 'skins)
skins
gosh> (define gourmet
(lambda (food)
(cons food (cons x '()))))
gourmet
gosh> x
skins
gosh> (cons x '())
(skins)
gosh> (gourmet 'onion)
(onion skins)
gosh> (set! x 'rings)
rings
gosh> (gourmet 'onion)
(onion rings)
gosh> (define gourmand
(lambda (food)
(set! x food)
(cons food (cons x '()))))
gourmand
gosh> (gourmand 'potato)
(potato potato)
gosh> x
potato
gosh> (gourmand 'rice)
(rice rice)
gosh> x
rice
gosh> (define diner
(lambda (food)
(cons 'milkshake (cons food '()))))
diner
gosh> (define dinerR
(lambda (food)
(set! x food)
(cons 'milkshake (cons food '()))))
dinerR
gosh> (dinerR 'onion)
(milkshake onion)
gosh> x
onion
gosh> (dinerR 'pecanpie)
(milkshake pecanpie)
gosh> x
pecanpie
gosh> (gourmand 'onion)
(onion onion)
gosh> (define omnivore
(let ((x 'minestrone))
(lambda (food)
(set! x food)
(cons food (cons x '())))))
omnivore
gosh> 'minestrone
minestrone
gosh> (omnivore 'bouillabaisse)
(bouillabaisse bouillabaisse)
gosh> (define gobbler
(let ((x 'minestrone))
(lambda (food)
(set! x food)
(cons food (cons x '())))))
gobbler
gosh> (gobbler 'gumbo)
(gumbo gumbo)
gosh> (define nibbler
(lambda (food)
(let ((x 'donut))
(set! x food)
(cons food (cons x '())))))
nibbler
gosh> (nibbler 'cheerio)
(cheerio cheerio)
gosh> (define food 'none)
food
gosh> (define glutton
(lambda (x)
(set! food x)
(cons 'more (cons x (cons 'more (cons x '()))))))
glutton
gosh> (glutton 'garlic)
(more garlic more garlic)
gosh> food
garlic
gosh> x
onion
gosh> (define chez-nous
(lambda ()
(set! food x)
(set! x food)))
chez-nous
gosh> food
garlic
gosh> x
onion
gosh> (chez-nous)
onion
gosh> food
onion
gosh> x
onion
gosh> (define chez-nous
(lambda ()
(let ((a food))
(set! food x)
(set! x a))))
chez-nous
gosh> (glutton 'garlic)
(more garlic more garlic)
gosh> food
garlic
gosh> (gourmand 'potato)
(potato potato)
gosh> x
potato
gosh> (chez-nous)
garlic
gosh> food
potato
gosh> x
garlic
gosh>


リポジトリの方にもcommitしてるのですが、外出先からPDA Net使ってgit pushしようとしたのですが繋がらないため、GitHubの同期はちょっと遅れてしまいそうです。ごめんなさい。





2011年9月7日水曜日

Scheme修行14章



14章では新しく第15の戒律、letが出てきます。進むにつれて第14、第12の戒律を組み合わせて少しずつ奇麗なコードへ。


letccで得た方位磁針を渡してskipするなど前章とちょっとだけ違う使い方をしてるのも面白かったです。


気づいた点等、とりあえずメモ書き。




  • 同じ式が繰り返しでてくるのはまずい


    • 関数を理解するのに同じ式を2回読まないといけない

    • 関数を読んでる人が理解しづらいのと、2回評価するからその分計算が増えるからいけてない



  • 繰り返される式に名前をつけるためにletを使う


    • 再帰関数に名前をつけるのにはletrecを使う(以前の章でやった)

    • letrecは多分let recursiveの略、letは何の略かな?

    • letは以下のλ式のシンタックスシュガー


      • (let ( (x1 α1) ... (xn αn)) β...)

      • ((lambda (x1 ... xn) β...) α1 ... αn)

      • λの仮引数x1...xnがα1...αnに束縛される

      • letrecは複数定義したのを相互に使えるけどletは駄目。

      • α1...αnを評価している環境の違いかな?





  • eqlist?はTheLittleSchemerでは自分で定義してた。(define eqlist? equal?)して代用。

  • letrecとletを使ってrember*を定義


    • avは何の略だろう?



  • 第15の戒律(仮)「繰り返される式の値に名づくるには(let ...)を用うべし。」


    • 「名づくる」「用う」初めて見た



  • rember1*を途中までrember*に空目してた

  • p70のdepth*は書き換えてテスト実行したけど確かに通らなかった


    • lが空か分かる前に(car l)の値に依存してしまっている



  • p73のdepthは非常に読みづらい


    • 1回しか評価されないのにletで名づくるのは読みづらくなったりする



  • 第15の戒律「関数定義において繰り返される式は、当の関数を1回使用するときに2回評価される可能性があるなら、それらの値を名づくるに(let ...)を用うべし。」

  • if文出てきた!


    • もっと前に知っておくべきだった?「何事にも、ふさわしい時と場所があるのです。」

    • (if α β γ)は(cond (α β) (else γ))と同じ

    • condを知ってればすっとifを理解出来る。

    • 答えによって2つに分かれる時ifを使うとcondよりも読みやすくなる



  • 最初のコードから掟に従いつつ構造を考えていくと可読性があがりますね


    • 比較するために1回、値を返すためにもう1回、合わせて2回評価してた

    • letで束縛すると2回評価しないでよくなってコードもすっきり

    • 2つに分岐するだけならifのがすっきり

    • やってることを抽象化してmaxを使えばすっきり

    • リファクタリングってこんな感じなのだろうか



  • letのbody部分に複数の式を置いてbegin的に使うなど

  • 「第14の戒律を用いるときに第13の戒律を忘れてはならない」


    • 関数を書き直していく時、今まで出てきた戒律を意識せねば。



  • letで順番よく実行している途中で答えを見つけたとき、抜け出すために方位磁針skipを使う


    • 継続を取り出してからマイナー関数に渡すことで、マイナー関数の中で値が求まった時に即座に返す事が出来る!



  • letccを使ったrember1*について


    • rember1*の中で、(car l)から何も取り除けなかったら方位磁針を使って戻って来る。

    • 取り除けた時はaを取り除いたリストを作りながら戻って来る。

    • 取り除けなかった時はnoっていうアトムを持って戻って来る。

    • 取り除けたら終わり、取り除けなかったらcdrで再帰

    • 方位磁針を使う事がないと分かっている場合は、0や'()を方位磁針として渡しても大丈夫。



  • tryを使うとちょうすっきり書ける。tryはマクロで書いた。


    • (try x a b)aの中でxを使うとaを抜けて、bを返す

    • 使わずにaを終了した場合、bは実行せず即座に値を返す




感想等


この章は結構ボリュームあった。休憩させるために「象を数えてみましょう。」とかそういうのが出て来るのが多かった気がする。


途中まではletの使い方で、2度評価される式に名前をつけたり、letをbeginのように使う使い方が出てきたり面白い。


後半数ページはletあまり関係なく継続の話だった。


引数でletccの方位磁針を受け取ったり、ifの条件式の中でletccを使うなど今までと違う使い方が出てきてこれもまた興味深い。


あと、tryを使うとなんだかものすっごいすっきり書けますね。


rmから結果を受け取って、rmの外側で成功したか判断して値を返すのではなく、


rm自身に失敗時の処理へ飛ぶ方位磁針を渡して渡しているのが面白い。


方位磁針を使わなかったら失敗時の処理へは飛ばず、rmの値が返る。


rmがその方位磁針を使うか使わないかをrmの内側で制御出来るようなイメージ。


方位磁針を使った時に返す値('no)をいじるともっと色々出来るのかな?


修行読みつつ(読み終わったら、になるかもしれないけど)プログラミングGauche読みます。


次の章への期待


この章まででかなり色々な関数の使い方を覚えました。


15章は表紙の絵だし、タイトルも「大人と子供の違い…」と、一区切り付きそうな印象。


時間をしっかり作りながら読んでいきたいと思います。


そういえば、バイト出始めたのでプライベートな時間ががくっと減って、働きながら勉強してって大変だなと思いました。


いつもおつきあい頂いてありがとうございます。 id:yamanetoshi となく!





2011年9月3日土曜日

Scheme修行13章



letcc - /var/log/messages


フライングされていたので早速13章を読みました。1度読んで2度目読む前にプログラミングGaucheの継続の章を斜め読みしたらちょっとすっきりしました。


その後バスの中でもう一度読んでソースコード書きながら読んで、再度メモを確認しつつ軽く読んだのでエントリを書きます。


letccについて


call-with-current-continuation、その略のcall/cc、継続の事です。


Scheme 修行 - /var/log/messages


を参考にgaucheのマニュアルのletccの項目Gauche ユーザリファレンス: 6.17 制御を読むと


(let/cc var body…)が(call/cc (lambda (var) body …))に展開されると書いてあります。


なのでlet/ccを使うことにしました。


メモ書き




  • (hop M)に遭遇する前にすべきことだった事を全て忘れて(letcc hop M)の値を求めたかのように振る舞う

  • (letcc hop ( (hop)を呼び出すまでの色々な手続き ) M)の色々な手続きを全部忘れてMのところまでジャンプすると考えちゃってもいいのかな

  • hopと唱えて、結果と一緒に正しい場所へ

  • 第14の戒律「(letcc ...)を用いて、値を直ちに、すばやく返すべし。」

  • どこかで覚えてた計算を忘れる

  • intersectallとrember-upto-lastで違うとこ


    • intersectallは結果が何かを知っている


      • 空集合が1つでもあれば、結果は空集合



    • rember-upto-lastはリストの部分が結果に「ない」か知っている


      • リストの中にaを見つけたら、リストの残りに結果がある。前の部分には「ない」。





  • consが結果を待ってるはずなのにconsしないでskipしてたり色々と面白い。

  • 結果をまたずに抜け出すとき、必要のない部分を捨てるときに使うと便利っぽい


    • 計算途中だった値はどこへいっちゃうんだろ



  • 継続についてはもうちょっと別の本やウェブサイト読まないと完全には理解出来てなさそうな感じがする


間違いかな?と思ったもの




  • p45の(null? (cdr lset))の質問の答えは真じゃないかな?

  • p49とp50のJの中のcondのmember?とelse?の結果の式は反対じゃないかな。


感想


再帰がどんなに深くても一番最初のとこまで戻って来れる! すごい!


継続はもっと色々な使い方が出来そうなのでScheme修行読んだらプログラミングGauche読んで再度勉強したい。


そういえば「再起」関数のtypoをオーム社さんのTwitterアカウントにmention飛ばしたんだけど返事が帰ってきてないので後でちゃんと窓口から連絡しようと思います。





2011年8月28日日曜日

Scheme修行12章



学園祭の準備をしつつ12章を読みました。学園祭が無事終了したのでブログのエントリをあげます。

11章では必要があれば一つ前の要素や今までの加算の結果や逆順のリストなど付加的な引数を渡す、第11の戒律を学びました。

JavaScriptのreduce - MDNと似た感じの印象を受けました。

12章ではletrecについて。

再帰する時に変化しない引数をletrecを使って除く方法、第12の戒律を学びます。

この章の名前は「避難しましょう」です。letrecのもう1つの使い方として、補助関数を守るための第13の戒律が出てきます。




メモなど




  • multiremberのYコンビネータを使った定義では一番外側のlambdaでaが束縛されるのでYコンビネータに渡す関数の中でaを使う事が出来る。

  • p18の動かないmrの定義


    • mrの中のaは束縛されていない自由変数

    • Schemeは静的スコープなのでmrが定義された時にaが値に束縛されてないとunbound variableとエラーが出て動かない。

    • mrを呼び出しているmultiremberの中の変数aはmrの定義時にはスコープの外、mrからはaが見えていない。

    • 試しにElispで書いたら動いた。Elispは動的スコープなので呼び出し元の環境の変数aを参照するため動く。

(defun mr (lat)
(cond ((null lat) '())
((eq a (car lat)) (mr (cdr lat)))
(t (cons (car lat) (mr (cdr lat))))))

(defun multirember (a lat)
(mr lat))

(multirember 'pie '(apple custard pie linzer pie torte))




  • p19にてα変換、α同値の話が出てくる。

  • p20 「再起関数」typo発見

  • p20 「(letrec ...)の名前づけ部分で定義された関数は囲まれている全ての(lambda ...)式の全ての引数を知っています。」


    • (letrec ( (mr ...) ) mr)はmrという名前の関数を定義して、その再帰関数を返している。

    • letrec中のmrは外側のlambdaの引数aを知っている。

  • letrecを使ったmultirember


    • mr pieを定義してlatに用いたように見える

    • p21下線のついたdefineは実際には存在しないけれどそのように想像することで理解の助けになる

    • mr pieはdefineを使って定義した関数と違って外側からは見えない!

  • 第12の戒律「再帰を適用している間に変化せぬ引数を除くには(letrec ...)を用いるべし。」

  • p23~p26でletrecを使ってmultirember-fを定義している。letrecの使い方は同じ。関数を定義して返す。

  • member?やunionなどを第12の戒律に従い書き直し。


    • member?の中のyes?で引数の名前がlなのはlatと被らないように?それとも短い名前がよかったから?

  • 関数を守る


    • unionの中のUは、unionが知っている事はすべて知っている。

    • unionの中にmember?の定義は出てこない

    • unionの動作はmember?に依存してる。member?の引数の順番が変わったら動かなくなってしまう。

    • letrecはかっこで囲んだ関数定義を複数おける。(condの条件みたいに)

    • そこで、unionの内側のletrecでmember?を定義する

  • 第13の戒律「関数を隠し、守るには、(letrec ...)を用いるべし。」


    • 補助関数はその関数にとって特別な値に使う。だから補助関数の定義が変わって変な値を返さないようにその場に隠す。

感想


letrecと(define (hoge) (define (fuga) ...) ...)

SICPでは補助関数はdefineの中でdefineを書いてた気がします。

defineの中にdefineだとどうなるんだろう、気になったので調べてみると

letrec - karetta.jp

letrecを使うか、defineの中にdefineを書くかは好みの問題です。

本当に好みの問題なのか気になったのでR5RSを読んでみると

Revised(5) Report on the Algorithmic Language Scheme

内部での定義を含む<ボディ>は、完全に等価なletrec式に必ず変換できる。例えば上記のlet式は次の式に等価である。

だそうで、やっぱり好みの問題らしい。

印象に残った部分

p28の

Q.

そのとおり。AはUとまったく同じ名前です。
どんな名前でもかまいませんよね。

A.

かまいませんが、定義を楽しみたい人にとって名前の選び方は大切です。

と書いてあったのがちょっと印象的。やっぱり関数の名前付けは大事。

Aじゃよく分からなくてもUだったらUnionのUだなって分かるので。

テスト

今まで

$ gosh test11.scm

とやってたのを

$ for i in `ls test*.scm`; do gosh $i; done

とするようにした。今回11.scmの中身も書き換えたのでいちいちgosh test11.scm、gosh test12.scmと2回やるのが面倒だったので。

シェルスクリプトも覚えないと orz

少し残った疑問と次章への期待

関数をどこらへんまで守るべきなんだろうか。

他にもmember?を使う関数があったらその関数も内部で同じmember?を持つので無駄な気もするんだけど。

member?が引数を決まった順序で取るという仮定が崩れないなら使ってもいいのかな…

とりあえず



  • 関数が他の関数の定義に依存すると、依存している関数の定義を変えたとき動かなくなってしまう

  • 動かなくなると困る関数はletrecで守る。隠す。

というのをしっかり頭に置きながら残りの章を読んで行きたいと思います。

どうやら次章でついに継続が出て来る! call/cc! call/cc!

楽しみです :)




2011年8月25日木曜日

Scheme修行11章



11章を読んでいたのでメモと感想をまとめてみます。


メモ




  • Scheme手習いの続きなので11から始まる。

  • 究極のλを知っていますか?

  • two-in-a-row-b?は2つの引数が変わるのに、質問は1つの引数についてのみ

  • p10「一方の引数は他方の引数について関数に何かを伝えます」


    • このトリックは面白い

    • two-in-a-row-bのprecedingではlatの引数の前の要素を

    • sum-of-prefixes-bのsonssfはこれまでの全ての数の合計を

    • scramble-bのrev-preは自分より前の部分の逆を



  • 第11の戒律「ある関数が、その関数に対する他の引数がいかなるものか知る必要があるときは、付加的な引数を用いるべし。」

  • 出てきてる用語


    • parsleyはパセリ

    • sardinesはイワシ

    • sonssfは「sum of numbers seen so far.(それまで見てきた数の合計)」の略

    • scrambleのニュアンスがちょっと分からない

    • rev-preはreversed prefix



  • 前章で定義してあったone?やpickなどの手続きを使っているので、11.scmの先頭に定義した


    • atom?等、他の章でも使うものは共通のファイルに抜き出していこうと思う。



  • 「関数の手がかりは、いつだってその名前です。」


    • いい名前は理解を助けてくれますね。



  • 食事の回数、3回


    • p13 「覚えているならアイスクリームを食べましょう」

    • p15 「スナックを食べる前に」

    • p15 「お茶の時間です。」




感想


「はじめに」によると「食べ物がちょっとした気晴らしになってこの本を一度にたくさん読まないで済むことを願っている」らしい。


でも面白いから読み始めると1章、一気に読んでしまいますね。


読んでから少し時間が経ってしまったので理解しているか確かめるためにthree-in-a-row?を定義してみた。



(define three-in-a-row-b?
(lambda (preceding1 preceding2 lat)
(cond ((null? lat) #f)
(else (or (and (eq? preceding1 preceding2)
(eq? preceding2 (car lat)))
(three-in-a-row-b? preceding2 (car lat) (cdr lat)))))))

(define three-in-a-row?
(lambda (lat)
(cond ((null? lat) #f)
((null? (cdr lat)) #f)
(else (three-in-a-row-b? (car lat) (car (cdr lat)) (cdr (cdr lat)))))))


で、n-in-a-row?を定義したくなったので色々といじっていたらいつの間にかYコンビネータを書いたり



(define Y
(lambda (f)
((lambda (x) (x x))
(lambda (x) (f (lambda (y) ((x x) y)))))))

(define L
(lambda (length)
(lambda (l)
(cond ((null? l) 0)
(else (+ 1 (length (cdr l))))))))

(define T
(lambda (take)
(lambda (nl)
(cond ((= 0 (car nl)) '())
(else (cons (car (car (cdr nl)))
(take (cons (- (car nl) 1)
(cons (cdr (car (cdr nl)))
'())))))))))
(define length (Y L))
(define take (Y T))

(define n-in-a-row?
(lambda (n)
(Y (lambda (n-in-a-row?)
(lambda (lat)
(cond ((> n (length lat)) #f)
(else (or ((Y ((lambda (a)
(lambda (every)
(lambda (lat)
(cond ((null? lat) #t)
((eq? a (car lat))
(every (cdr lat)))
(else #f)))))
(car lat)))
(take (cons n (cons lat '()))))
(n-in-a-row? (cdr lat))))))))))


それを無名にしてみたり



(define n-in-a-row?
(lambda (n)
((lambda (f)
((lambda (x) (x x))
(lambda (x) (f (lambda (y) ((x x) y))))))
(lambda (n-in-a-row?)
(lambda (lat)
(cond ((> n (((lambda (f)
((lambda (x) (x x))
(lambda (x) (f (lambda (y) ((x x) y))))))
(lambda (length)
(lambda (l)
(cond ((null? l) 0)
(else (+ 1 (length (cdr l)))))))) lat)) #f)
(else
(or (((lambda (f)
((lambda (x) (x x))
(lambda (x) (f (lambda (y) ((x x) y))))))
((lambda (a)
(lambda (every)
(lambda (lat)
(cond ((null? lat) #t)
((eq? a (car lat)) (every (cdr lat)))
(else #f)))))
(car lat)))
(((lambda (f)
((lambda (x) (x x))
(lambda (x) (f (lambda (y) ((x x) y))))))
(lambda (take)
(lambda (nl)
(cond ((= 0 (car nl)) '())
(else (cons (car (car (cdr nl)))
(take (cons (- (car nl) 1)
(cons (cdr (car (cdr nl)))
'())))))))))
(cons n (cons lat '()))))
(n-in-a-row? (cdr lat))))))))))


なんかこの章の理解を確かめるというより究極のlambda復習してしまった orz





2011年8月22日月曜日

Scheme修行の11章を読む前に



Scheme手習いを読み終わったのでScheme修行を読みます。


本文の前に




  • 訳者前書き

  • 序文

  • はじめに


があるのでまずは気になったところのメモと感想など書きます。


訳者前書き


メモ



  • Scheme手習いと同じ著者による続編

  • 2冊合わせてSchemeの入門書として完結


    • なのでScheme手習いの続き、11章から始まっている



  • Scheme手習いと同じく質問と答えのペア

  • 前作は「再帰的」な考え方、今回は継続と代入

  • 他の言語にも継続に似た機能はある


    • Lispの例外(catch throw)やCのsetjump, longjump

    • 大域的な脱出手段なので後から使えない(のかな?)

    • Schemeの継続はいつでも使用することは可能



  • Scheme手習い・Scheme修行ではSchemeの制御構造については継続をのぞいては触れられていない


    • 末尾再帰最適化の話とか


      • Schemeは静的束縛なのでそれが実現出来るらしい

      • 動的な束縛をする言語では実現出来ない

      • 似たような言語だからといってLispで同じことをやるとスタックが溢れる





  • letccを実現するためにletccを使っているので本書で作成しているインタプリタはSchemeでしか実現出来ない

  • 継続渡しスタイルについて調べてみるのも面白い


感想

スタックの話でもあったけどSchemeはLispの方言とは言うがLispとは別物のよう。


Lispによって変数のスコープも違えば言語で規定されてる機能も全然違いそう。


継続渡しスタイルについては後で継続渡しスタイル - karetta.jpを読もうと思う。


ということはSchemeじゃないLispにはSchemeにない機能もあるに違いないので読み終わったら取り組む。


実はPractical CommonLisp読んでる途中でやめちゃいましたので。


序文


メモ



  • 「もし誰かに魚をあげたら、一日食べることができる。もし誰かに釣りを教えたら、一生食べることができる。」

  • Lispは元々「LISt Processor」、リスト処理

  • Lispはリストだけでなく計算を行う関数を持っている。リストはLispの心臓、関数は魂。

  • 生きるためには食べ物以外のものも必要。釣りを習いましょう!


感想

リストが心臓で関数が魂ってなんかアツい!


確かにLispにはどっちも欠かせない気がする。


リストが心臓で関数が魂なら、マクロは一体なんだろう?


序文の最初に出て来る言葉は深い。


ググってみたけど中国のことわざ?元ネタが分からないです orz





はじめに


メモ



  • 「この本の目的は、読者に計算の性質について考えることを教えることにある。」

  • プログラミング言語は、計算の性質を伝える最も良い方法、数学と違い直接体験出来る

  • プログラミングの実用的な世界への入門書ではないが、計算の性質を理解する出発点

  • ガイドライン


    • 急いで読んではだめ。5回未満で読み切ろうとしないこと。(ちなみにScheme手習いには2回未満で読み切ろうとしないこと、と書いてる)

    • 飛ばして後ろから読んではだめ。少しずつ難しくなっていくので完全に理解してから進む。

    • 「読みながら例を試してほしい」

    • 「この本では形式的な定義はしない。読者が自分の定義を形式化し、覚えて理解するほうがよいと信じているからである」

    • しかし戒律はその先を読む前に知って理解しておくこと。

    • プログラミングのこつはデータおよび処理のパターンを認識すること。




感想

最後に「次のページで読者を待っている挑戦を楽しんでほしい。」と書いていた。なので、Scheme修行も楽しみながら読むぞ!


ガイドラインに書かれていたように、本にちりばめられたヒントから自分の定義を形式化し、覚え、理解したい。


ちりばめられたヒントを拾うためにも5回ぐらい読まないと気づかない点があるんだと思う。


計算の性質について考えれば、一生プログラマで食べていくこと、出来るかな?





2011年8月12日金曜日

Scheme修行を読む。



Scheme手習いについて


Scheme手習いを読み終わりました。


Scheme手習い







本読んで内容を書いてhanachin/TheLittleSchemer ? GitHubにアップしてブログを書いてid:yamanetoshiさんに読んだエントリ投入のお知らせを書いて、疑問点等補足してもらって…という感じで読み進めました。

エントリあげる間隔はちょっとゆっくり目でしたが orz

ひとまず一冊読み終える事が出来て嬉しいです。

Scheme手習いの冒頭には2度以下で読むなと書いてあったので今度は同級生の方ともう一度読んでみようかと思ってます。

Scheme修行について


続編のScheme修行も購入しました。


Scheme修行







以前から手元にあって、手習いを読み終わったら読もうと思ってわくわくしていた本です。

手習いを読み終わった翌日、もう我慢出来なくなってしまって早速読書用のリポジトリhanachin/TheSeasonedSchemer ? GitHubを建ててマクドナルドに居座り一気に1章読んでしまいましたw

前回の書き方

前回は質問に対応したテストを読みながら書いていって、その質問の答えを定義して、テストが通るか確認して、というTDD的な流れで進めました。

テストケースのファイルを章ごとに1.scm、2.scm、3.scm...と作っていって、テスト用のマクロをtest-util.scmで少しだけ定義してテストケース冒頭で読み込み、本に出て来る関数の定義は全部func.scmの1ファイルに書いて、という感じの構成にしてみましたが最終的にfunc.scmが985行になりました。

全部1つに定義しちゃうと1章ごとにやった内容を確認しづらいし区切りがつけづらいかな、と思ったり。

あとコミットメッセージも謎の英語でぱっと見分からなかったような orz

今回はどうしよう

テストケースを書いてから答えを書く姿勢はそのままで行こうと思います。

テストケースになりそうな質問を本文から全て拾ってから答えを考え読み進めるようにします。

ファイルの構成は、前回func.scmが大きくなったのをふまえ、それぞれの章で使う関数の定義や質問の答えを11.scm、12.scm、13.scm...という風に1章1ファイルで書いていこうかと。

よく重複して定義してしまう関数は別途切り出したり、前章で定義した関数を使う際はloadで前章を読み込もうかと。

テストケースはtest11.scm、test12.scm、test13.scm...のようにtestを頭につけて1章1ファイルずつ作っていきます。

加えてnotes.orgにメモを取って、それもgitで管理する事にします。

後、コミットメッセージを日本語でちゃんと書くようにしてみます。

目標


前回、1章読む間隔が結構あいてしまったので1週間に1章は読むようにして、3ヶ月以内に読了していけるように頑張りたいです。

Scheme手習いだと2回以下で読み切るな、だったのがScheme修行だと5回以下で読み切るな、となってるので前回以上に読み込まなければならないですね…

楽しんで読めると嬉しいな。1章読んだエントリは後ほどあげます。