/home/matstani/weblog

programming log.

Clojureアプリケーションを動的に書き換える

nREPLサーバをClojureアプリケーションに組み込んでおくと、動作中のClojureアプリケーションに接続して、デバッグを行ったり、動作を書き換えたりすることができます。

試しに、デスクトップGUIアプリケーションを動的に書き換えてみます。
Clojureからは、JavaのSwingを直接利用できますが、せっかくなので、よりClojureっぽく書けるSeesawを使ってみます。

project.cljは以下のとおり。

アプリケーションのコードは以下のとおり。

6行目でnREPLサーバを起動しています。

アプリケーションを起動

1
$ lein run

以下のようなウィンドウが表示されます。

ウィンドウ

「Show Message」ボタンを押すとメッセージが表示されます。

ウィンドウ

このアプリケーションにnREPLクライアントで接続し、動作を書き換えてみます。
nREPLクライアントとして、nrepl.elを利用する場合、Emacs内で以下のコマンドを実行します。

1
2
3
M-x nrepl
Host: 127.0.0.1
Port: 7888

Portで指定するのは、アプリケーション中のstart-serverで指定したポート番号です。 以下のようにnREPLプロンプトが表示されます。

1
2
; nREPL 0.1.7
user> 

表示されるメッセージを変化させてみます。

1
2
user> (in-ns 'nrepl-test.core) ;namespaceセット
nrepl-test.core> (def msg "Changed Message.") ;msgを再定義

ボタンを押すと、メッセージが変化します。

ウィンドウ

ログ機能を付けてみます。

1
2
3
4
nrepl-test.core> (let [old show-msg-actn]
    (defn show-msg-actn
        [e]
        (println "LOG: show-msg-actn") (old e))) ;show-msg-actnを再定義

ボタンを押すと、コンソールにログが表示されるようになりました。

screen内のEmacsでparedit.elを使う

Clojureなど、Lisp系言語の編集に便利なparedit.elですが、GNU screen内で起動したEmacsで利用しようとしたところ、Ctrl-矢印キーが使えず(5C, 5Dなどと入力される)、飲み込みや吐き出しの操作ができませんでした。

emacs起動時のコマンドでTERM変数を指定しておくと、とりあえず解決するようです。

1
TERM=xterm emacs -nw somefile

参考にしたURL http://lists.gnu.org/archive/html/screen-users/2009-12/msg00037.html

Clojureのuseをrequireで置き換える

Clojureで他の名前空間を参照する方法として、requireとuseがありますが、Clojure1.4以降では、require単独でuseと同様にプレフィックス無しでの参照ができるようになっています。

requireにまとめることで、コードが若干すっきりするかもしれません。
サンプルコード

Clojure開発環境インストール手順(Emacs)

推奨環境、手順はこまめに変化するようなので、2013年4月時点での手順のメモ。

  • 2014/07/16 nrepl.el -> ciderに変更、リンク先修正。
  • 2014/08/13 CIDER 0.7.0 リリースに合わせて、leinプラグインの記述を追加

利用するのは、Emacs+CIDER
ちなみに、Clojure Programmingで紹介されているSLIME, swankの利用はdeprecatedとのこと。

Javaのインストール

Ubuntuの場合

1
$ sudo apt-get install openjdk-7-jdk

CentOSの場合

1
$ sudo yum install java-1.7.0-openjdk

leiningenインストール

1
2
3
$ curl -O https://raw.github.com/technomancy/leiningen/stable/bin/lein  
$ mv lein ~/bin  
$ chmod 755 ~/bin/lein  

Emacsのインストール

Emacs24以降のバージョンを利用すると、パッケージ管理システムが標準で同梱されているので、以降の手順が簡単。

.emacsに以下追記

追記後、Emacs上で以下のコマンドを実行すると、直ちに有効になる。

1
M-x eval-buffer

ここでインストールされるパッケージは以下のとおり。

  • clojure-mode
    Clojure編集の基本機能を追加するモード。インデントやシンタックスハイライトなど。
  • ParEdit
    括弧のペアを管理してくれるモード。開き括弧の入力時に自動的に閉じ括弧を入れてくれたり、括弧(S式)単位での編集ができたり。
    動作が直感的でないところもあるので、チュートリアルで勉強。
  • CIDER
    Emacsから、nREPL(ネットワーク経由で利用できるREPL)にアクセスするための機能。
    nREPLサーバをアプリケーションに組み込んでおくと、動作中のアプリケーションの情報を取得したり、動的にパッチを当てたり、色々できる。
  • RainbowDelimiters
    Lispにありがちな多重括弧を、キレイに色付けしてくれるモード。

cider-nreplプラグインインストール

CIDER 0.7.0以降では、leinプラグインと協調して動作するようになっています。インストールのために、以下の記述を~/.lein/profiles.cljに追記します。

1
:plugins [[cider/cider-nrepl "0.7.0"]]

~/.lein/profiles.cljが存在しない場合は、以下の内容で新規に作成します。

1
{:user {:plugins [[cider/cider-nrepl "0.7.0"]]}}

Clojureプロジェクト作成

1
$ lein new demo

Emacs上でnREPL起動

1
2
$ cd demo
$ emacs src/demo/core.clj

Emacs上で

1
M-x cider-jack-in

lib-noirを利用したフォームバリデーション

Compojureプロジェクトの作成手順はこちら

Compojureベースのウェブアプリケーションで、フォームバリデーションを行います。

ウェブアプリケーション用ライブラリlib-noirを利用するコードを紹介します。

依存ライブラリのインストール

lib-noirとHTML生成ライブラリのHiccupを追記します。
project.clj

:dependenciesに追記後、以下のコマンドでライブラリをインストールします。

1
$ lein deps

lib-noir/validationを使ってフォームバリデーション

フォームからPOSTされた日付データ、時刻データを、正規表現でチェックするコードです。バリデーションが失敗した場合は、エラーメッセージを表示しています。
handler.clj

Octopressのスタイルシートを変更

ドキュメントにあるとおり、Octopressでは、ソースコードを簡単に貼り付けできます。 gistのコードを埋め込むには以下のように記述します。

1
{% gist gist_id [filename] %}

このgistの埋め込み結果なのですが、Octopressのデフォルトのスタイルだと、テーブルの枠幅がでこぼこになって見た目が悪かったので、スタイルシートを微調整しました。 sassディレクトリ以下のscssファイルを修正すると、サイトに反映されるようです。

今回はsass/custom/_styles.scssに以下を追記しました。

1
.gist .line-data { width: 100% }

近いうちに本体でも修正されるとは思いますが。

Friendを利用したフォーム認証

Compojureプロジェクトの作成手順はこちら

Compojureベースのウェブアプリケーションで、フォーム認証を行なってみます。

Friendという認証/認可用のライブラリを利用できます。

依存ライブラリインストール

project.cljの:dependenciesにFriend、HTML生成ライブラリのHiccupを追記します。

:dependenciesに追記後、以下のコマンドでライブラリをインストールします。

1
$ lein deps

Friendを使ってフォーム認証

仮アカウントとしてadmin、userを用意し、それぞれ閲覧できるページが異なる設定にしています。 認証に伴うリダイレクト処理はFriendが行ってくれます。
サンプルコード

Compojureでファイルアップロード

Compojureプロジェクトの作成手順はこちら

Compojureベースのウェブアプリケーションで、ファイルアップロードを行います。

依存ライブラリのインストール

HTML生成ライブラリとしてHiccupを利用するので、以下のように追記します。
project.clj

:dependenciesに追記後、以下のコマンドでライブラリをインストールします。

1
$ lein deps

ファイルアップロード

アップロードされたファイルを、プロジェクトのルートディレクトリに保存するコードです。
handler.clj

KormaでDBアクセス

Compojureプロジェクトの作成手順はこちら

Compojureベースのウェブアプリケーションで、データベースから読みだした値を表示してみます。

ClojureのJDBCラッパーも十分に高機能なのですが、より柔軟にSQLを構築できるKormaというライブラリを使う手順を紹介します。なお、以下の手順ではSQLiteを使っています。

データベース準備

1
2
3
4
$ mkdir db
$ sqlite3 db/helloworld.sqlite3 "CREATE TABLE items (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT);"
$ sqlite3 db/helloworld.sqlite3 "INSERT INTO items (title) VALUES ('最初のアイテム');"
$ sqlite3 db/helloworld.sqlite3 "INSERT INTO items (title) VALUES ('2つ目のアイテム');"

依存ライブラリインストール

project.cljの:dependenciesにJDBCドライバーとKorma、HTML生成ライブラリのHiccupを追記します。
project.clj

:dependenciesに追記後、以下のコマンドでライブラリをインストールします。

1
$ lein deps

Kormaを使ってデータベースから読み出し

handler.clj

Clojureインストール、Compojureプロジェクト作成

Clojureには、Leiningenという管理ツールがあり、Clojure本体のインストールや、各種ライブラリのインストール、プロジェクトの作成などがとても簡単にできるようになっています。

Clojureがインストールされていない状態から、ウェブアプリケーションフレームワークCompojureを利用したウェブアプリケーションの開発用プロジェクトを作成するまでの手順は以下のとおりです。

Javaがインストールされていることを確認

1
$ java -version

Leiningenインストール

leinスクリプトをダウンロード
1
$ curl -O https://raw.github.com/technomancy/leiningen/stable/bin/lein
ダウンロードしたスクリプトをPATHの通った場所に置き、実行権を付与
1
2
$ mv lein ~/bin
$ chmod 755 ~/bin/lein 

compojureプロジェクトの作成(初回は時間かかる)

1
$ lein new compojure helloworld 

開発用HTTPサーバ起動(初回は時間かかる)

1
2
$ cd helloworld
$ lein ring server-headless 

Port3000でHTTPサーバが起動されるので、ブラウザで確認します。