clojureでswingでドラッグ&ドロップ。するだけ。

(import
 (java.awt FlowLayout)
 (java.awt.event ActionListener WindowListener WindowAdapter)
 (java.awt.dnd DropTarget DropTargetAdapter DnDConstants)
 (java.awt.datatransfer DataFlavor)
 (javax.swing JFrame JTextArea JDialog JPanel JScrollPane JButton JLabel BoxLayout))
(use 'clojure.string)

(defn dnd-listener [f]
  (proxy [DropTargetAdapter] []
	 (drop [e]
	       (apply f [e]))))

(defn drop-target [f]
  (let [dt (DropTarget.)]
       (doto dt
	     (.addDropTargetListener (dnd-listener f)))))

(defn dnd-panel [f]
  (let [panel (JPanel.)]
       (doto panel
	     (.add (JLabel. "please drop."))
	     (.setDropTarget (drop-target f)))))

(defn dnd-frame [f]
  (let [frame (JFrame.)]
       (doto frame
	     (.add (dnd-panel f))
	     (.addWindowListener
	      (proxy [WindowAdapter] []
		     (windowClosing [e]
				    (System/exit 0))))
	     (.setSize 640 480)
	     (.setVisible true))))

(defn dnd-data-from-event [event]
  (let [transfer (.getTransferable event)]
       (.getTransferData transfer DataFlavor/javaFileListFlavor)))

(defn dnd-data-process [f]
  (fn [event]
     (.acceptDrop event DnDConstants/ACTION_REFERENCE)
     (apply f [(dnd-data-from-event event)])))

(defn list-panel [strs]
  (let [panel (JPanel.)]
    (.add panel (JTextArea. (join "\n" strs)))
    (.setSize panel 460 200)
    panel))

(defn vbox-layout [coll]
  (let [panel (JPanel.)]
    (.setLayout panel (BoxLayout. panel BoxLayout/PAGE_AXIS))
    (doseq [c coll] (.add panel c))
    panel))

(defn invoker-dialog [func files]
  (let [dialog (JDialog.), button (JButton. "Execute")]
    (.setLayout dialog (FlowLayout.))
    (doto button
      (.addActionListener
        (proxy [ActionListener] []
 	  (actionPerformed [e]
            (doseq [f files]
              (apply func [f]))))))
    (doto (.getContentPane dialog)
      (.add
        (vbox-layout
          [(list-panel
             (map (fn [file] (.getAbsolutePath file)) files))
           button])))
    (doto dialog
      (.setSize 480 320)
      (.setVisible true))))

(defn drop-start [func]
  (dnd-frame
    (dnd-data-process
      (fn [files] (invoker-dialog func files)))))

(drop-start println)

clojureはrubyと比べるとファイル処理というかテキスト処理が面倒な気がする。
contribとかもっと調べればいいライブラリがあるのだろうか。
とりあえずユーティリティを書く。
IO.foreachより短いタイプでテキスト処理したいがためにeach-linesアナフォリックマクロを作成。

(defn reader-from-path [path]
  (BufferedReader. (InputStreamReader. (FileInputStream. path))))

(defmacro read-lines [path]
  `(with-open [r# (reader-from-path ~path)]
     (loop [coll# [] line# (.readLine r#)]
       (if line#
         (recur (conj coll# line#) (.readLine r#))
         coll#))))

(defmacro each-lines [path & body]
  `(doseq [~'line (read-lines ~path)]
     ~@body))

バグってても知らない。

(defn ! [x]
  (loop [val x n (- x 1)]
    (if (> n 1)
      (recur (* val n) (- n 1))
      val)))

(defn ** [x n]
  (reduce * (repeat n x)))

(defn **2 [x]
  (* x x))

(defn combination [n m]
  (if (< n m) (throw (ArithmeticException.)))
  (/ (! n)
     (* (! m)
        (! (- n m)))))

(defn average [seq]
  (/ (reduce + seq) (count seq)))

(defn variance [seq]
  (let [avg (average seq)]
    (average (map (fn [x] (** (- avg x) 2)) seq))))

(defn stddev [seq]
  (Math/sqrt (variance seq)))

(defn correlation [seq]
  (let [col1 (map first seq), col2 (map second seq)]
       (let [avg1 (average col1)
	    avg2 (average col2)]
	    (/ (reduce + (map
			   (fn [d]
			       (*
				(- (first d) avg1)
				(- (second d) avg2))) seq))
	        (count seq)
         	(* (stddev col1) (stddev col2))))))

(defn vector-length [vec]
  (Math/sqrt
    (reduce + (map **2 vec))))

(defn vector-from-points [p1 p2]
  (map (fn [x] (- (first x) (second x))) (map list p1 p2)))

(defn distance [p1 p2]
  (vector-length (vector-from-points p1 p2)))