--- title: もう一度第七章をはじめから author: kazu634 date: 2008-08-31 url: /2008/08/31/_1092/ wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4247;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - gauche - Lisp ---

「手続き」は、数値、文字列、真偽値と同様、「値」として他の変数に束縛したり、引数として他の手続きに渡したり、他の手続きの戻り値として返したりできます。

ここらへんはややトリッキーだけど、Cとかでも関数ポインタとかあったはず。Javaとかだと、オブジェクト型を渡していたりするから、そこらへんと同じ感じなんだろう…と思う。

foldってトリッキー

(define (print_element lis)
(fold (lambda (a b) (print a)) #f lis))

foldは順番にlisを処理する。ちなみに「(lambda (a b) (print a)」という無名関数への引数は順番に次のようになるよ(lisが「(1 2 3 4 5)」の場合):

第一引数 第二引数
1 #f
2 1
3 2
4 3
5 4

となることに注意。なんか自分の直感に反している。

ようやく自分が何が理解できていないのかわかった!

「高階手続き」がわかっていないんだ!これをキーワードに勉強していこう!

高階手続き(Wikipediaから)

関数を戻り値とする関数

(define (add x y)
(+ x y))))

このaddを次のように書き直す

(define (add x)
(lambda (y) (+ x y)))

これを使って加算をするには、次のように書く。

> ((add 2) 3)
5

ここで、まず(add 2)の戻り値は1つ引数をとって2を足す関数になる。そして、戻り値として返ってきた関数に、更に3を渡して最終的な計算結果を得ている。つまり、add自身は関数を戻り値とする高階関数となっている。 上記のような、n引数ある関数を、1引数だけの高階関数に変換する操作をカリー化と呼ぶ。

高階関数 – Wikipedia

なんかよくわからなかったんだけど、わかった瞬間がきた!

つまり

(define (reversed walker)
(lambda (proc lis)
(walker proc (reverse lis))))

のreversedという手続きは「一つ引数をとって、戻り値として二つの引数をとる手続きを返す」ってことなんだ!(間違えてない…はず。大丈夫だよね。。。)