Clojureの現実的なコード 括弧も怖くないよ
Shibuya.lispで、プログラミングClojureを買ったまま、何もできずにいましたが、ようやく、動き出しました。結局プログラミングClojureを真面目に1ページずつ読み進める忍耐力が無く、実際にコードを書きながら覚えることにしました。運良く、Clojureの練習にちょうどいい問題を見つけてクリップボード履歴ツールを作ってます。
https://sourceforge.net/projects/clclcl/
clclclのコードをちょっと紹介してみます。 @fm021さんに、Java方面のアドバイスを貰ったりしたのですが、ちょっとコードを見せるとやはり括弧が怖いという感想を頂いてしまったのでJavaコードと比較しながら、どうなってるか説明してみます。
クリップボードアクセスのnamespaceのソースコード
Clojureのコードです。クリップボードの内容を取得する関数 clipboard-get とクリップボードに値を設定する関数 clipboard-set で構成されてます。
(ns clclcl.clipboard (:gen-class) (:import (java.awt Toolkit) (java.awt.datatransfer Clipboard DataFlavor StringSelection UnsupportedFlavorException))) (defn clipboard-get [] (let [clip (.getSystemClipboard (Toolkit/getDefaultToolkit))] (if (.isDataFlavorAvailable clip DataFlavor/stringFlavor) (try (.getData clip DataFlavor/stringFlavor) (catch UnsupportedFlavorException _ nil))))) (defn clipboard-set [str] (let [selection (StringSelection. str) clip (.getSystemClipboard (Toolkit/getDefaultToolkit))] (.setContents clip selection nil)))
では、それぞれ簡単に見てみます。
namespaceの定義
(ns clclcl.clipboard (:gen-class) (:import (java.awt Toolkit) (java.awt.datatransfer Clipboard DataFlavor StringSelection UnsupportedFlavorException)))
最初の ns はnamespaceの定義です。Javaではパッケージによる階層化がありますが、Clojureではnamespaceです。:import の部分で、参照するJavaのクラスをimportしてます。Javaのimportなので、以下と同等です。
import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.UnsupportedFlavorException;
クリップボードの内容取得
簡単に言うと、defnというのは、関数を定義するものです。letというのはレキシカルスコープを生成するものです。
(defn clipboard-get [] (let [clip (.getSystemClipboard (Toolkit/getDefaultToolkit))] (if (.isDataFlavorAvailable clip DataFlavor/stringFlavor) (try (.getData clip DataFlavor/stringFlavor) (catch UnsupportedFlavorException _ nil)))))
対応するJavaコードは以下です。
public String getClipboard() { Clipboard clip = Toolkit.getDefaultToolkit(); if (clip.isDataFlavorAvailable(DataFlavor.stringFlavor)) { try { return clip.getData(DataFlavor.stringFlavor); } catch (UnsupportedFlavorException e) { //do nothing. } } }
これは、素直にjavaコードを翻訳しただけでclojureコードができあがります。Javaのクラス名、メソッド名ばかりなので、対応も取りやすいと思います。
クリップボード設定
(defn clipboard-set [str] (let [selection (StringSelection. str) clip (.getSystemClipboard (Toolkit/getDefaultToolkit))] (.setContents clip selection nil)))
対応するJavaコードは以下です。
public void setClipboard(String str) { StringSelection selection = new StringSelection(str); Clipboard clip = Toolkit.getDefaultToolkit(); clip.setContents(selection, null); }
これも、素直にjavaコードを翻訳しただけですね。
javaと対比させて見ても異常という程、括弧が多い訳じゃないと思うんだけどな。これでもう括弧も怖くないでしょ?