SICPを読む(48) 2.2.1(3) map

とうとうmapが出てきた。mapは,perlruby等にもある結構有名な関数。僕はforeachやeachを使っていたので、mapを使用することは殆ど無かった気がする。Schemeのmapを使うことで何かが変わるのだろうか?

map

(define (map proc items)
  (if (null? items)
      `()
      (cons (proc (car items))
            (map proc (cdr items)))))

(map (lambda (x) (* x x))
     (list 1 2 3 4))
; (1 4 9 16)

リスト全てにprocを適用できる。ふむふむ。

mapなら、「リストに何をするのか」を書くだけで良い。インデックスが・・・と考える必要が無くなるので。

mapを使う → プログラムがすっきりする → 見通しが良くなる → 更に高い抽象 → ウマー

となる(はず)

脚注のmapが凄い

凄かったのが脚注のmap。

(map +
     (list 1 2 3)
     (list 4 5 6)
     (list 7 8 9))
; (12 15 18)

なんじゃこら〜〜〜〜〜〜〜〜〜〜〜〜!!

こんな発想全然無かったよ・・・。

階層構造は次節に出てくるので、次節で本物のmapを作ってみようと思う。

僕のschemeレベル

僕のschemeレベルを確認しておこう。

Scheme:Schemeプログラマのレベル10

レベル3
  • mapの便利さに目覚めて、なんでもかんでもリストにしてからmapしまくる。 letrecやinternal defineによるローカル関数定義を多用するようになる。
  • 自分のwebサイトのドキュメントをSchemeを使ったフィルタで生成するとか、普段から使える個人用のプログラムをSchemeで書き始める。後に、そのコードの半分はsrfi-1とsrfi-13にある関数の再実装であったことに気づく。
  • call/ccを非局所脱出やコルーチンに使ってみて、なるほど、確かに動くな、と思うが、それ以上の応用は思い浮かばない。
  • 普段常用するマシンに色々な処理系をインストールしまくる。
  • たまにC言語に戻った時に printf("%s: %d?n" name value); と書いて何故コンパイルエラーになるのか悩む。
  • mapを覚えた,let多用気味になりそう。
    • let, let*, letrec letrecで再帰できるlambdaが作れる。ほうほう。なるほど。letrecも多用しよう〜。
  • Schemeを使ったフィルタで生成はやってない。
  • 普段から使える個人用のプログラム - ボチボチやり始めた。
  • コルーチンのサンプルコピペしたり(でも継続はわからず)
  • 処理系をインストールしまくったり
  • printf("%s: %d?n" name value);って何か間違ってますか?

レベル2.8くらいまで到達したきがする。mapしまくるぞぉ〜〜〜。

Schemeプログラマのレベル5 - 簡易版

簡易版を作ってみた。

  • なんでも再帰(レベル1)
  • なんでもラムダ(レベル2)
  • なんでもマップ(レベル3)
  • なんでもクロージャー(レベル4)
  • なんでも継続(レベル5)

僕がなんでも継続(レベル5)となる日は来るのだろうか!?先は長いぞ!!