Daysこの広告は、90日以上更新していないブログに表示しています。15日目の記事です)はじめにClojureアイドルことしょぼちむさんが先日開催されたClojure夜会で、Clojureで書かれた女子力botなるものについて発表していました。Clojure歴3週間とのことでしたが、そうとは思えないほどよく書けています。Clojureのidiomaticな書き方の中には、時間を書けて慣れていかないとなかなかすんなり書くことが難しいものもあります。そこで、今回は女子力botを題材によりClojureっぽいイケてる書き方を紹介します。書き換えてみよう今回ピックアップする項目は以下のとおりです。clojure-contribは使わないようにしようシーケンス処理に持ち込もう*-in関数を使おう状態をloopで持ち回そう参照を公開しないようにしよう(ここで取り上げていないすべての変更を含めた最終版はこちらから確認できます。)それでは順番に見て行きましょう。clojure-contribは使わないようにしようまず最初に注目するのはこちら。mention))3行目でclojure.contrib.str-utilsがrequireされています。clojure.contrib.str-utilsというのは、いわゆるレガシーcontribあるいはモノリシックcontribと呼ばれるライブラリの一部です。contribライブラリの過去の形態で、Clojure標準には含まれない準標準的な機能をひとまとまりのJARとして配布していたものです。レガシーcontribはすでにdeprecatedな扱いになっていて、保守もされていません。レガシーcontribの多くの機能はClojure標準に取り入れられているか、同様の機能を提供するモジュラーcontribが用意されているので、特別な理由がなければそれらを使うようにすれば問題ありません。ここで使われているstr-utilsも、多くの機能が現在のClojure標準におけるclojure.stringから提供されていて、str-utils/re-subにはclojure.string/replaceが相当します。Go*-in関数を使おうつづいて注目するのは次のコードです。word2))))この関数register-wordは以下のように使います。register-wordは、ネストしたマップを使って、2つの単語が連続して出現する回数を管理します。Clojureではこのように、ネストしたマップやベクタを非破壊的に更新していくような使い方をよくします。ネストを辿るたびにgetやassocを繰り返すのは煩雑です。そこで、Clojureはこういったネストしたデータを扱うのに便利な関数(get-in/assoc-in/update-in)を準備しています。さきほどのregister-wordはupdate-inを使うと次のように書くことができます。0)))シーケンス処理に持ち込もう次はこちら。tokens))))reduceに引数として渡しているfnの中身がやや複雑です。最初のトークンが空でなければregister-wordで2つのトークンを登録する。それ以外の場合は何もしないといった処理です。これを整理してみると、以下のことが分かります。token-wordはすべてのトークンに対して適用しているので、fnの中ではなくてreduceに渡すシーケンスにあらかじめmapしておけばいい隣り合うトークンの組からなるシーケンスから、最初のトークンが空の組をフィルターしておけばfnの中で条件分岐しなくて済むこのようにfnの中の処理を整理すると、複雑だった処理がより単純なシーケンス処理の組み合わせとして書き直すことができます。Clojureはシーケンスに対する便利な関数を非常にたくさん持っているので、複雑に絡んだ処理もシーケンス処理に持ち込むことで、組込み関数の組み合わせで書くことができるようになるかもしれません。load-text関数を上の考えのしたがって書き直すとこのようになります。{})))適宜スレッディングマクロ(->>)を使うことで、処理の見通しがさらによくなり、バグを埋め込みにくくなります。状態をloopで持ち回そうさらにこちら。2))))atomを使って、繰り返しごとに変化する状態を管理しています。idiomaticなClojureコードでは、繰り返しで変化する値をループで持ち回すことで状態を管理します。new))))ループで書くとコードが著しく複雑になるようなケースを除けば、上のように非破壊的に状態を更新していくやり方の方が好まれます。参照を公開しないようにしよう最後はやや設計に絡む話。tweettxt))))initの中では、ref型の*words*にロードしたデータを代入するようになっています。これを利用する側は、initを呼び出した後に*words*を直接参照します。...)Clojureには破壊的に変更できるatomやrefといった参照型が用意されています。参照型を使う場合には、「それがどこで変更されうるか」に気をつける必要があります。参照型を外部へ公開すると、外部で何の制約もなしに参照を変更される可能性があります。そのため、参照型をそのまま公開するのは極力避けた方がいいでしょう。今回の場合には、initでロードしたデータを*words*に代入するのではなく、load-text関数をパブリックなインタフェースとし、ロードしたデータを保持することは利用する側の責任とすることで、参照型を公開するのを避けることができます。...)おわりに今回は女子力botを題材によりClojureっぽい書き方について紹介しました。時間をかけて「じっくりとClojureのidiomaticな書き方を知りたい!」という場合は、Clojureの本に当たることをおすすめします。Cookbookこれらの本は、Clojureらしい書き方を教えてくれるだけでなく、「なぜそう書くのか」についてもきちんと説明されているのでオススメです。7日...2011-04-16「ClojureでJavaクラスのコンストラクタをapplyする」をリフレクションで元ネタは1年前の記事。4はてなブログをはじめよう!athosさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。