読者です 読者をやめる 読者になる 読者になる

Programmer's Note

コード読み書きの備忘録。

Clojureメモ:forを使う

Clojureを始めて1週間ちょいといったところか。 とりあえず本を読んでいる、ちょくちょく試してみている感じ。

ループのまわし方とかも、手続き型プログラミングと勝手が違って戸惑う。

Clojureのforは命令型言語のforループとは違うらしい。(リスト内包表記と呼ばれる。)

forの一番シンプルな例。

user=> (for [i [0 1 2 3]] (println i))
0
1
2
3
(nil nil nil nil)

最後の(nil ...)は関数の返り値をREPL環境が表示している。 (for ...)は制御文ではなく関数なので戻り値がある。 (for ...)はつまり、ループ分だけ要素があるコレクションを作って返すということか。

さて、ループをまわすには、要はまず何かの集合が必要だということだな。 上記の例だと、集合[0 1 2 3]の中から一個ずつアイテムを取り出してiに代入し、それを使って処理している。 (Clojureの用語だとシンボルiに値をバインドする、と言う。)

上記はClojureベクター(要は配列)を使ったが、次にマップを使ってみる。

user=> (def a {:m1 1 :m2 2})
#'user/a
user=> a
{:m1 1, :m2 2}
user=> (for [i a] (println i))
[:m1 1]
[:m2 2]
(nil nil)

おお、期待通りの動作。マップの順番って定義された順だろうか・・・まあ、あとで調べるとしよう。

1から10の数字を表示する関数を書いてみる。 1〜10をまわすが、[1 2 ...]で定義するのも面倒で、range関数を使う。

user=> (range 1 11)
(1 2 3 4 5 6 7 8 9 10)

でとりあえず、

user=> (for [i (range 1 11)] (println i))
1
2
3
4
5
6
7
8
9
10
(nil nil nil nil nil nil nil nil nil nil)

てな感じだ。