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と対比させて見ても異常という程、括弧が多い訳じゃないと思うんだけどな。これでもう括弧も怖くないでしょ?