じゅういっこめ

プログラミングを本で独学することの難しさ(あるいは楽しさ)

Clojure を勉強してて、以下のような記述に出会った。

(defn add-points [& pts]
  (vec (apply map + pts)))

(add-points [10 10] [-1 0])
-> [9 10]

『プログラミング Clojure 第2版』p.132

で、これについての詳しい説明は特にない。
特に説明しなくてもわかるでしょ、というところかな。
しかし、こちらは初心者だから、わからない。

どこがわからないかというと、

(apply map + ...

と、関数が3つ並んでいるのがなぜなのか、わからない。

map は + を 引数(シーケンス) のそれぞれに適用してる。
じゃ、apply はなに?

調べると、apply は、(apply f seq) とあると、関数 f を
シーケンスの各要素に適用するということみたい。

となると、ますますわからなくなってくる。

なぜ、apply と map が並んでいるの?

結論からいうと、引数pts についての理解不足だった。

(def print-pts [& pts]
  (println pts))

としてみるとよくわかる。

(print-pts [10 10] [-1 0])
-> ([10 10] [-1 5])

というように、[10 10] と [-1 0] からなるシーケンスなのだった。

だから、

(apply map + pts)

(apply map + '([10 10] [-1 0]))

あるいは

(apply map + [[10 10] [-1 0]])

ということになる。

で、(9 10) という結果が返ってくるから、

(vec '(9 10))
-> [9 10]

と ベクタに変換している。

このことがわかるのに、2日かかった。
もちろん、仕事したり他のことしながらだけど。

教室などで教わっていると、こういうのは先生が一発で教えてくれるだろう。
このあたりが、独学の難しさであるが、こういう廻り道が楽しかったりするのである。

参考

『プログラミング Clojure 第2版』
Stuart Halloway / Aaron Bedra 著
川合史朗 訳
オーム社
平成25年 4月 25日 第2版第1刷