「なぜRubyは許容可能なLISPなのか - 翡翠はコンピュータに卵を生むか」という記事が面白かった。

この記事の中でサンプルコードを使って、 プログラムの読みやすさを対比させていた部分があったので、 Clojureでやってみたくなった。

[ 1 , 2 , 3 ].map {| n | n*n }.reject {| n | n% 3 == 1 }

( 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に匹敵する読みやすさになる。

とはいえ、しょっぱなはかなり戸惑ったけどね…。