WindowsでClojure
鉄分豊富な人が遊びにやって来た。一泊して酒を酌み交わし親交を深めた訳であるが、翌日はどうすべ? って、話になったよ。そこはそれ、磁石に吸い寄せられるように、大宮にある 鉄道博物館 へ、行ってみようとあっさり決まった。実はおいらも行った事無いんだよね。(昔々、秋葉原と言うか神田の それには行ったけど)
ちょいっと早めに着いたけど、長蛇の列になってましたよ。列の大半は小さい子供さんを伴った家族連れ。 おいらみたいな、中年おじさん連は浮いていた。自動発券機で1000円のスイカもどきのカードを買って 改札を通りました。本物のスイカも勿論使えます。
家族連れのお目当ては、各種シュミレーターの予約券Getで、列を成してました。TDLみたいな雰囲気 ですな。おいら達は、まずは2階へ、一番乗りでした。壁に沿って、鉄道の歴史が展示されてて、思わず 昔にトリップしてしまいましたよ。そして、一角には、日本一大きいと言うジオラマ(鉄道模型)室が ありました。鉄道の一日を約10分に渡って解説してました。始発電車、始発新幹線が動き出し、夕刻には 夜行寝台の北斗星とかが動き、ああ、あれに乗って北海道まで行ったなあなんて思いだしました。 また、資料室は地味だけど、ヘッドプレート等がたくさん展示されてて面白かった。国鉄が終了する時 の、さおようなら国鉄(1987.3.31)、よろしくJR(1987.4.1)のプレートが感慨深いでした。
一階には、お召し列車の展示とかSLとかいろいろあって、全部乗ってみるとどのくらい時間がかかる のだろう? 連れは何度も来たいと申しておりました。12時から始まる、SL機関車の転回台運用は 必見です。途中で鳴らす汽笛が何とも言えないいい味を出してましたね。
昼は中で売っている駅弁を買って食べるべし。いろいろあって迷っちゃうぞ。いろいろ買ってお土産に するのもいいかも。おいらは、お土産に、石炭あられ(竹炭入りで石炭とそっくり、土産で一番人気とか)と、銚子 電鉄のぬれせんべいを買いました。連れは、2Fのショップでしか手に入らないというグッズ類を 大量に買ってましたよ。
WindowsでClojure
今までずっと歴史物をやっていたけど、そろそろ飽きてきたので現代に戻ります。暫く前にClojureが 1,1から1.2になりました。Wnidowsに入れている Clojure-Box でも、1.2にしようと思って、*.jarだけ1.2に入れ替えたのはいいんだけど、構成が変わって微妙な 警告が出てくるようになりました。このまま使っていてもいいんだろうけど、ちと気分が悪いので 新たに入れなおしました。 あの人 も始めたようですし、本も読み直しています。
で、どうせ整備するなら、少し使いやすいようにしようと、環境整備編に(性懲りもなく)走って しまうのでした。何するか? WindowsだってLein使いたいよね。Leinって、Clojure界のデブロイ 環境です。(あっ、正確には開発環境だけど、おいらは、出来上がったjarファイルをひとまとまりに して、Clojureも入っていないPCに持って行ける事に価値を見出しています)
github に行って、lein-win32.zipとleiningen-1.3.1-standalone.jarを落としてきて、適当なdirに両者を 入れ、Pathを通せば出来上がり。使い方と言うかサブコマンドは、Lein help すれば出てきます。
余勢を駆ってFreeBSDでも
やってみよう。Linuxでの解説はいろいろあるもんで。。。
問題は、Windows上にあるClojure-boxもどきをどう作るかです。emacsには便利な ELPA と言うのが提供されているので、今回はこれを利用する事にします。
まず上記の指示に従って、パッケージリストを取り寄せます。emacsを再起動してから M-x package-list-package すると、インストール可能なパッケージが出てくるので、swank-clojureと pareditの所で I を押します。(インストールするパッケージの選択)続いて X を押すと、実行 (インストール)されます。途中でエラーが発生するかも知れませんが無視しても大丈夫です。 これで、関連する便利パッケージも自動的に入ります。emacsでファイルを閲覧する時にキー操作が 面倒だと思ったら、ついでに less も入れておくといいです。M-x less-minner-mode すれば、emacsがless に変身してくれます。Windowsみたいな貧弱な環境だと超便利!
paredit-modeは、開き括弧に対する閉じ括弧(いわゆるコッカ)を自動で挿入してくれる 機能があります。また文字列を囲むダブルクォートも2つ自動で挿入してカーソルがその間に位置 してくれるので、カッコやダブルクォートの閉じ忘れを防止出来ます。設定は、.emacsに
(autoload 'paredit-mode "paredit"
"Minor mode for pseudo-structurally editing Clojure code." t)
(add-hook 'clojure-mode-hook (lambda () (paredit-mode +1)))
(add-hook 'slime-repl-mode-hook (lambda () (paredit-mode +1)))
と書いておきます。
ついでに、leinも入れておくと吉。lein new project-nameした後、project-name-dir内に自動 生成される project.cljに
:dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]]
を追加し、lein depsすると、便利機能が追加されます。
こうしておいて、lein swankした後で、emacsを起動し、slime-connect すると、便利です。
例題
clojure本もいいけど、もっと他にないかと探してみると
に、L5という面白いものが掲載されてた。試してみよっと。
試してみた。FreeBSDで作った L5.jar をWindowsへ持ってきて、サンプルを動かしてみたらちゃんと 動いた。これぞClojure(Java)の威力。(jarファイルのダブルクリックで、起動するなんて、ちょっと びっくりです。これって、leinが気を利かせてくれてるから?)
秋だから絵を描こう
(ns simple-plotter
(:import (javax.swing JFrame JPanel )
(java.awt Color Graphics Graphics2D Image))
(:use (clojure.contrib def)))
;; This is an attempt to make graphics in clojure as simple as it was on a ZX
;; Spectrum. Let us count the whole maven/leiningen/cake-clojure-emacs-(require
;; 'simple-plotter) thing as being a one-time effort equivalent to persuading
;; one's father to buy a ZX Spectrum in the first place.
;; Define some colours to use:
;; java.awt.Color/GREEN -> simple-plotter/green
(defmacro- defcolours [& colours]
(list* 'do (map #(list 'def (symbol (. (str %) toLowerCase)) (symbol (str "Color/" (str %)))) colours)))
(defcolours black blue cyan darkGray gray green lightGray magenta orange pink red white yellow)
;; Private machinery
(defn- draw-lines [lines #^Graphics2D g2d xs ys]
(doseq [[x1 y1 x2 y2 color] @lines]
(. g2d setColor color)
(. g2d drawLine (* xs x1) (* ys y1) (* xs x2) (* ys y2))))
(defn- render-lines-to-graphics [lines paper-color height width
#^Graphics2D g w h ]
(doto g
(.setColor @paper-color)
(.fillRect 0 0 w h))
(draw-lines lines g (/ w @width) (/ h @height)))
(defn- primitive-repaint [plotter]
(. (plotter :panel) repaint))
(defn create-plotter [title width height ink paper]
(let [lines (atom [])
height (atom height)
width (atom width)
paper-color (atom paper)
panel (proxy [JPanel] []
(paintComponent [g]
(proxy-super paintComponent g)
(render-lines-to-graphics
lines paper-color height width
#^Graphics2D g
(. this getWidth)
(. this getHeight))))
frame (JFrame. title)]
(doto frame
(.add panel)
;; The extra space 2,32 is taken up by the window decorations
;; in GNOME. How to get that from the OS?
(.setSize (+ @width 2) (+ @height 32))
(.setVisible true))
{:height height
:width width
:ink-color (atom ink)
:paper-color paper-color
:current-position (atom [0,0])
:lines lines
:panel panel}))
(defn- primitive-line [plotter x1 y1 x2 y2]
(let [ink @(:ink-color plotter)]
(swap! (:lines plotter) conj [x1 y1 x2 y2 ink]))
(primitive-repaint plotter))
(defn- set-paper-color [plotter color]
(swap! (plotter :paper-color) (constantly color))
(primitive-repaint plotter))
(defn- set-ink-color [plotter color]
(swap! (plotter :ink-color) (constantly color)))
(defn- set-current-position [plotter [x y]]
(swap! (plotter :current-position) (constantly [x y])))
(defn- remove-lines [plotter] (swap! (plotter :lines) (constantly [])))
(defn- make-scalars [points xleft xright ytop ybottom]
(let [xmax (reduce max (map first points))
xmin (reduce min (map first points))
ymax (reduce max (map second points))
ymin (reduce min (map second points))]
[(fn[x] (+ xleft (* (/ (- x xmin) (- xmax xmin)) (- xright xleft))))
(fn[y] (+ ybottom (* (/ (- y ymin) (- ymax ymin)) (- ytop ybottom))))]))
(defvar- current-plotter (atom nil))
;; ;; Public Interface
(defn create-window
([] (create-window "Simple Plotter"))
([title] (create-window title 1024 768))
([title width height] (create-window title width height white black ))
([title width height ink paper]
(let [plotter (create-plotter title width height ink paper)]
(swap! current-plotter (constantly plotter))
plotter)))
;;Makes a version of a function with an implicit first argument of plotter, and
;;a default version with no first argument is not supplied, and which uses
;;current-plotter instead.
(defmacro ddefn [fnname args & body]
`(defn ~fnname
(~args (~fnname @~'current-plotter ~@args))
([~'plotter ~@args] ~@body)))
(ddefn plot [x1 y1]
(primitive-line plotter x1 y1 x1 y1)
(set-current-position plotter [x1 y1]))
(ddefn cls []
(remove-lines plotter)
(primitive-repaint plotter))
(ddefn plot [x1 y1]
(primitive-line plotter x1 y1 x1 y1)
(set-current-position plotter [x1 y1]))
(ddefn draw [dx dy]
(let [[x1 y1] @(plotter :current-position)
[x2 y2] [(+ x1 dx) (+ y1 dy)]]
(primitive-line plotter x1 y1 x2 y2)
(set-current-position plotter [x2 y2])))
(ddefn line [x1 y1 x2 y2]
(plot plotter x1 y1)
(draw plotter (- x2 x1) (- y2 y1)))
(ddefn ink [color] (set-ink-color plotter color))
(ddefn paper [color] (set-paper-color plotter color))
(ddefn scaled-scatter-plot [points xleft xright ytop ybottom scalepoints]
(let [[xsc ysc] (make-scalars (take scalepoints points) xleft xright ytop ybottom)]
(doseq [[x y] points]
(plot (* (xsc x))
(* (ysc y))))))
(defn window [plotter]
(swap! current-plotter (fn[x] plotter)))
(ddefn get-height [] @(plotter :height))
(ddefn get-width [] @(plotter :width))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Examples
(defn sine-example[]
(create-window "sine")
(cls)
;; sine graph
(doseq [x (range 1024)]
(plot x (+ 384 (* 376 (Math/sin (* Math/PI (/ x 512)))))))
;; axes
(ink yellow)
(plot 0 384) (draw 1024 0)
(line 512 0 512 1024))
(sine-example)
上記をREPL画面に貼り付けると、お試しの正弦波が別画面に表示されます。
;; (use 'simple-plotter)
(defn transform [[xx xy yx yy dx dy]]
(fn [[x y]] [(+ (* xx x) (* xy y) dx)
(+ (* yx x) (* yy y) dy)]))
(def barnsleys-fern '((2 [ 0 0 0 0.16 0 0 ])
(6 [ 0.2 -0.26 0.23 0.22 0 0 ])
(7 [ -0.15 0.28 0.26 0.24 0 0.44 ])
(85 [ 0.85 0.04 -0.004 0.85 0 1.6 ])))
(defn choose [lst] (let [n (count lst)] (nth lst (rand n))))
(defn iteration [transforms]
(let [transform-list (mapcat (fn [[n t]] (repeat n (transform t))) transforms)]
(fn [x] ((choose transform-list) x))))
(def barnsley-points (iterate (iteration barnsleys-fern) [0 1]))
(create-window "Barnsley's Fern" 350 450)
(ink green)
(scaled-scatter-plot (take 10000 barnsley-points) 50 300 50 400 100)
続いて、上記を貼り付けると。。。 色は秋色の方が良かったかしら?
初心(これでウブと読むんだってさ)でも clojure してみよう
ウブンツでもやってみんべぇ。
sudo apt-get install maven2 vi pom.xml mvn clojure:repl
たったこれだけで、Clojureを始められます。劣化したS式であるxmlを事前に準備するのが 面倒ですが。(下記をpom.xmlとして用意) 初回は、あれこれ御取り寄せするので、プロンプトが出てくるまで、ちと時間がかかります。なお、REPL は、ヒストリー機能付きになってるので、矢印キー等で過去に入力したS式を簡単に呼び出せます。
それから、事前にJDKを入れておくのをお忘れなく。Sunのやつでもopenなやつでも、お好きにどうぞ。 嗚呼、もうSunのJDKじゃ無いんですね。Javaの生みの親 James Gosling はオラクルを辞めちゃったし いろいろとごたごた してるみたいだし。ごたごたついでに、Lambada は λ にしてね。Clojureは、Lambdaの代わりを fn が 務めているよ。変わらない事がStatusというCLは、結局独自追加が祟って非互換性が生まれるんでしょうな。 だったら、最初から互換性なんて期待しなければいいのに。
話が逸れちゃったわい。FreeBSDで使ってるJavaは
[sakae@cdr ~]$ java -version java version "1.6.0_07" Diablo Java(TM) SE Runtime Environment (build 1.6.0_07-b02) Diablo Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing) [sakae@cdr ~]$ javac -version javac 1.6.0_07
こんなのでした、って、普通の人には参考にならないよね。後、
mvn clojure:swank
お好みで、emacsから、M-x slime-connectするのもいいでしょう。
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>hello-maven-clojure-swank</artifactId>
<version>1.0-SNAPSHOT</version>
<name>hello-maven</name>
<description>maven, clojure, emacs: together at last</description>
<repositories>
<repository>
<id>clojars</id>
<url>http://clojars.org/repo/</url>
</repository>
<repository>
<id>clojure</id>
<url>http://build.clojure.org/releases</url>
</repository>
<repository>
<id>central</id>
<url>http://repo1.maven.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>clojure</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>clojure-contrib</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
<version>0.9.94</version>
</dependency>
<dependency>
<groupId>swank-clojure</groupId>
<artifactId>swank-clojure</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.theoryinpractise</groupId>
<artifactId>clojure-maven-plugin</artifactId>
<version>1.3.3</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>1.2</version>
</plugin>
</plugins>
</build>
</project>
MyMEMO: Swap CapLock and Control Key
REGEDIT4 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout] "Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,1d,00,3a,00,3a,00,1d,00,00,00,00,00
キーボード配列をWindows上で変更すると Windows キーボードレイアウトの変更。 これ、自分へのメモ。だったら、ここに書くなちゅうに!