Clojure の Leiningen で以前挫折をした。いやむしろ SLIME がちゃんと動かなくて嫌になった。
@making さんの LT "Clojure+Leiningenで3分Hadoop" で Clojure の Leiningen がちゃんと動いくことの確信を得たのでリトライする。
目標は
  - Leiningen でプロジェクトを作る。
- Leiningen で swank server を起動して、SLIMEでインタラクティブ開発。
- 単体実行 jar の作成。
シェルで次を実行。a はプロジェクト名。
 lein new a
./a/project.clj を編集
  - lein swank で swank server を起動するために :dev-dependencies を追加
- lein uberja で作る単体実行 jar のエントリポイントを指定する :main を追加
(defproject a "1.0.0-SNAPSHOT"
  :description "FIXME: write"
  :dependencies [[org.clojure/clojure "1.1.0"]
                 [org.clojure/clojure-contrib "1.1.0"]]
  :dev-dependencies [[leiningen/lein-swank "1.1.0"]]
  :main a.core)
シェルで次を実行し依存ライブラリの取得後、swank server を起動する。
 lein deps
lein swank
Emacs から M-x slime-connect とすると、ちゃんと SLIME 動いた。補完もちゃんと動いた。別途、Emacs + SLIME まわりの設定は必要なので、それは後述する。
./a/src/a/core.clj を編集
  (ns a.core
  (:gen-class))
(defn -main [& args]
  (. javax.swing.JOptionPane (showMessageDialog nil "Hello World")))
シェルで
 lein uberjar
chmod +x ./a-standalone.jar
./a-standalone.jar
以上、目標達成。
後述予定の Emacs + SLIME まわり。
github から swank-clojure と clojure-mode を git clone しておく。 ~/.emacs の設定は SBCL の最新 SLIME とかぶらないように無理をしている。うまく両立する方法はないものだろうか?おまけに Google App Engine を SLIME から起動しようとしたときの残骸も残ってる。
 (defun clojure ()
  (interactive)
  (add-path "~/letter/clojure/lib/clojure-mode")
  (add-path "~/letter/clojure/lib/slime")
  (add-path "~/letter/clojure/lib/slime/contrib")
  (eval-after-load "slime"
    '(progn
       (slime-setup '(slime-repl
                      slime-fuzzy
                      slime-banner))
       (setq slime-complete-symbol*-fancy t)
       (setq slime-complete-symbol-function 'slime-fuzzy-complete-symbol)
       (global-set-key [(control ?\;)] 'slime-selector)
       (loop for (key command) in
             '(([(control ?c) ?\;]              slime-insert-balanced-comments)
               ([(control ?u) (control ?c) ?\;] slime-remove-balanced-comments)
               ([(control ?c) ?\;]              slime-insert-balanced-comments)
               ("\C-j"                          slime-eval-print-last-expression)
               ("\C-m"                          newline-and-indent)
               ("\C-i"                          slime-indent-and-complete-symbol))
             do (define-key slime-mode-map key command))))
  (setq swank-clojure-classpath
        '("~/letter/java/eclipse-workspace/moeopa-clj/src"
          "~/letter/java/eclipse-workspace/moeopa-clj/war/WEB-INF/classes"
          "~/letter/clojure/lib/swank-clojure/src"
          "~/letter/clojure/lib/clojure/clojure.jar"
          "~/letter/clojure/lib/clojure-contrib/clojure-contrib.jar"
          "~/letter/clojure/lib/appengine-clj/appengine-clj.jar"
          "~/letter/clojure/lib/compojure/compojure.jar"
          "~/letter/clojure/lib/compojure/deps/commons-codec-1.3.jar"
          "~/letter/clojure/lib/compojure/deps/commons-fileupload-1.2.1.jar"
          "~/letter/clojure/lib/compojure/deps/commons-io-1.4.jar"
          "~/letter/clojure/lib/compojure/deps/jetty-6.1.15.jar"
          "~/letter/clojure/lib/compojure/deps/jetty-util-6.1.15.jar"
          "~/letter/clojure/lib/compojure/deps/servlet-api-2.5-20081211.jar"
          "~/local/opt/appengine-java-sdk/lib/appengine-tools-api.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/appengine-local-runtime-shared.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/geronimo-el_1.0_spec-1.0.1.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/geronimo-jsp_2.1_spec-1.0.1.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/geronimo-servlet_2.5_spec-1.2.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-ant-1.6.5.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-ant-launcher-1.6.5.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-commons-el-1.0.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-commons-logging-1.1.1.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-jasper-compiler-5.0.28.jar"
          "~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-jasper-runtime-5.0.28.jar"
          "~/local/opt/appengine-java-sdk/lib/impl/appengine-api-labs.jar"
          "~/local/opt/appengine-java-sdk/lib/impl/appengine-api-stubs.jar"
          "~/local/opt/appengine-java-sdk/lib/impl/appengine-api.jar"
          "~/local/opt/appengine-java-sdk/lib/impl/appengine-local-runtime.jar"
          "~/local/opt/appengine-java-sdk/lib/impl/agent/appengine-agentruntime.jar"
          "~/letter/clojure/lib/programming-clojure/lib/ant.jar"
          "~/letter/clojure/lib/programming-clojure/lib/ant-launcher.jar"))
  (setq slime-lisp-implementations
        `((clojure
           ("java"
            "-classpath"
            ,(concat ".:classes:"
                     (mapconcat 'identity
                                (mapcar 'expand-file-name
                                        swank-clojure-classpath)
                                ":"))
            "clojure.main"
            "--repl")
           :init swank-clojure-init)))
  (load
   (expand-file-name "~/.emacs.d/elpa/package.el"))
  (package-initialize)
  (require 'clojure-mode)
  (require 'slime-autoloads)
  (slime)
  )
Leiningen からコマンド一発で Google App Engine の雛形プロジェクトが作成できたらいいのにな。
ということで making さんありがとうございました。
今回の Shibuya.lisp もよかったです。みなさんありがとうございました。
Common Lisp 的にはちょっとさびしかったな。