Clojure + ClojureScript 動かしてみたのでメモ

下記書籍の Clojure + ClojureScript サンプルを動かしてみたのでメモ。

ClojureScript: Up and Running: Functional Programming for the Web

ClojureScript: Up and Running: Functional Programming for the Web

構成

  • Clojure
    • Ring
    • Compojure
  • ClojureScript
    • Domina

プロジェクトの新規作成

lein new client-server

編集

src
 clj
  client-server
   server.clj
 cljs
  client-server
   client.cljs
resources
 public
  index.html

  • projent.clj
(defproject client-server "0.1.0-SNAPSHOT"
 :plugins [[lein-cljsbuild "0.2.7"]]
 :dependencies [[org.clojure/clojure "1.4.0"]
                [org.clojure/clojurescript "0.0-1450"]
                [domina "1.0.0"]
                [compojure "1.1.0"]
                [ring/ring-jetty-adapter "1.1.1"]]
 :source-paths ["src/clj"]
 :main client-server.server
 :cljsbuild {
   :builds [{
       :source-path "src/cljs"
       :compiler {
         :output-to "resources/public/client.js"
         :optimizations :whitespace
         :pretty-print true}}]})
  • server.clj
(ns client-server.server
  (:require [compojure.route :as route]
            [compojure.core :as compojure]
            [ring.util.response :as response]
            [ring.adapter.jetty :as jetty]))

(defn eval-clojure [request]
  (try
    (let [expr (read-string (slurp (:body request)))]
      (pr-str (eval expr)))
    (catch Throwable t
      (str "ERROR: " t))))

(compojure/defroutes app
  (compojure/POST "/eval" request (eval-clojure request))
  (compojure/GET "/" request
    (response/resource-response "public/index.html"))
  (route/resources "/"))

(defn -main []
  (prn "View the example at http://localhost:4000/")
  (jetty/run-jetty app {:join? true :port 4000}))
  • client.cljs
(ns client-server.client
  (:require [goog.net.XhrIo :as xhr]
            [domina :as d]
            [domina.events :as events]))

(def result-id "eval-result")
(def expr-id "eval-expr")
(def button-id "eval-button")
(def url "/eval")

(defn receive-result [event]
  (d/set-text! (d/by-id result-id)
               (.getResponseText (.-target event))))

(defn post-for-eval [expr-str]
  (xhr/send url receive-result "POST" expr-str))

(defn get-expr []
  (.-value (d/by-id expr-id)))

(defn ^:export main []
  (events/listen! (d/by-id button-id)
                  :click
                  (fn [event]
                    (post-for-eval (get-expr))
                    (events/stop-propagation event)
                    (events/prevent-default event))))
  • index.html
<html>
  <head>
    <title>ClojureScript Client-Server Example</title>
  </head>
  <body>
    <h1>ClojureScript Client-Server Example</h1>
    <form id="eval-form">
      <p><label for="eval-expr">
          Enter a Clojure expression to evaluate on the server:
      </label></p>
      <p><input id="eval-expr" name="eval-expr" type="text" size="70" /></p>
      <p><input id="eval-button" type="button" value="Eval" /></p>
    </form>
    <p>The result:</p>
    <pre id="eval-result">
    </pre>
    <script src="/client.js" language="javascript"></script>
    <script type="text/javascript" language="javascript">
        client_server.client.main()
    </script>
  </body>
</html>

ClojureScriptのコンパイル

lein cljsbuild once

実行

lein run

確認

Webブラウザで以下を開く。