RubyとLispとClojureのコードの読みやすさ
「なぜRubyは許容可能なLISPなのか - 翡翠はコンピュータに卵を生むか」という記事が面白かった。
この記事の中でサンプルコードを使って、 プログラムの読みやすさを対比させていた部分があったので、 Clojureでやってみたくなった。
Ruby
[1,2,3].map {|n| n*n }.reject {|n| n%3==1 }
LISP
(remove-if (lambda (n) (= (mod n 3) 1)) (mapcar (lambda (n) (* n n)) '(1 2 3)))
(Clojure以外のLisp系言語はよく知らないが、たぶんこれはCommon Lisp)
同じことをClojureで記述してみる
Clojureのlambdaは無名関数なので、同じことをやると以下のようになる。
(remove (fn [n] (= (mod n 3) 1)) (map (fn [n] (* n n)) [1 2 3]))
上記LISPよりかは読みやすいが、ほぼ同等だな。
リーダーマクロ#()
を使ってみると。
(remove #(= (mod % 3) 1) (map #(* % %) [1 2 3]))
ぐっと簡潔になった。 さらに、スレッディングマクロを使うと、 Rubyのメソッドチェーンのように処理の流れの通りに書ける。
(->> [1 2 3] (map #(* % %)) (remove #(= (mod % 3) 1)))
一行の場合
(->> [1 2 3] (map #(* % %)) (remove #(= (mod % 3) 1)))
スレッディングマクロは、かなりプログラムの読みやすさに貢献している。 慣れてしまえばこれはRubyに匹敵する読みやすさになる。
とはいえ、しょっぱなはかなり戸惑ったけどね…。