2013年1月7日月曜日

煩雑な Javaコードを簡単な Clojure に直してみる

仕事始めでつかれたが、寝る前にちょっと Clojure やってみる。

以下は、Neal Ford の 『プロダクティブ・プログラマ』に載ってるのとほぼ同じコードで、ファイルを読み込んでから行番号をつけて標準出力に書き出すというもの。

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class LineNumbers {
    public static void main(String...args) {
        File file = new File("sample.txt");
        LineNumberReader reader = null;
        try {
            reader = new LineNumberReader(new FileReader(file));
            while (reader.ready()) {
                System.out.printf("%d:%s%n",
                        reader.getLineNumber(), reader.readLine());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException ignored) {}
        }
    }
}

本ではこの後、Groovy を使うと同じ処理がいかに簡単に書けるかというくだりに続くわけだけど、今日はこれをClojure で書いてみる。

(use 'clojure.java.io)
(def zip (partial map vector))
(with-open [r (reader "sample.txt")]
  (doseq [[n line] (zip (iterate inc 1) (line-seq r))] 
    (printf "%d:%s%n" n line)))
なるほど。
  • Haskell 等でよく使う zip は、 (partial map vector) で、代用できるらしい。
  • try で囲って finally の中でリソースを開放する辺りまでを、with-open で書けるらしい。C# のあれみたいだな。
  • doseq の代わりに map とかを使うと、printf が返す nil が行数分返されてきてしまう。
  • Haskell でいう [1..] みたいのは (iterate inc 1) と掛ける。無限リストは iterate でなんとかするのが定石らしい。
  • Groovy ほどではないが、Java よりは簡潔に書ける。

寝よ。

0 件のコメント:

コメントを投稿