前回 、MacのEmacsでmozc.elを使うために、mozc-serverをビルドする手順を紹介しました。しかしその手順でビルドできない方がいたので、別の方法を試してみます。
今回はmozc-serverを仮想マシンで動かします。
- Vagrant
- VirtualBox
が必要です。
手順
結果
mozc.elが動きました。
mozc.elが動けばac-mozcも動くはずです。
Mozcは、Google 日本語入力のオープンソース版のIMEです。 そしてmozc.elは、Mozcを使ってEmacsで日本語入力するためのEmacs Lispです。
今回は、Mac上のEmacsでmozc.elを使って日本語入力できるようにします。
EmacsとMozcは以下のような感じで通信しているみたいです。
[Emacs + mozc.el] <-- S式 --> [mozc_emacs_helper] <-- IPC --> [Mozc server]
EmacsとMozc serverが通信するのにmozc_emacs_helperが必要ですが、公式にはMac上でのビルドに対応していません。
なのでビルド用のスクリプトをちょっといじって、ビルドできるようにしました。
公式のMacBuildInstructionsには
とあります。Qtはオプションということなので今回は無しでビルドします。
私は OS X 10.9.2 + Xcode 5.1.1 で実行しました。
詳細は公式のMacBuildInstructionsも参照してください。
ソースコードの取得
$ cd ~/ $ svn co http://src.chromium.org/svn/trunk/tools/depot_tools $ export PATH=`pwd`/depot_tools:"$PATH" $ mkdir -p ~/src/mozc $ cd ~/src/mozc $ gclient config http://mozc.googlecode.com/svn/trunk/src $ gclient sync
gclient syncで
Error: Command svn checkout https://src.chromium.org/chrome/trunk/src/tools/clang/scripts@171017 ...
みたいなエラーが出ましたが気にしないことにします。
build_mozc.pyを上書きします。
$ cd ~/src/mozc/src $ curl -O https://raw.githubusercontent.com/igjit/mac-emacs-mozc/master/build_mozc.py
ビルドの実行
$ python build_mozc.py gyp --noqt $ python build_mozc.py build_tools -c Release $ python build_mozc.py build -c Release mac/mac.gyp:GoogleJapaneseInput mac/mac.gyp:gen_launchd_confs unix/emacs/emacs.gyp:mozc_emacs_helper
インストールします。
$ sudo cp -r out_mac/Release/Mozc.app /Library/Input\ Methods/ $ sudo cp out_mac/DerivedSources/Release/mac/org.mozc.inputmethod.Japanese.Converter.plist /Library/LaunchAgents $ sudo cp out_mac/DerivedSources/Release/mac/org.mozc.inputmethod.Japanese.Renderer.plist /Library/LaunchAgents
ここで一旦GUIをログアウトします。 再ログイン後にMozcが使えるようになります。
動作確認
$ cd ~/src/mozc/src $ echo -e '(0 CreateSession)\n(1 SendKey 1 97)' | out_mac/Release/mozc_emacs_helper ((mozc-emacs-helper . t)(version . "1.13.1651.101")(config . ((preedit-method . roman)))) ((emacs-event-id . 0)(emacs-session-id . 1)(output . ())) ((emacs-event-id . 1)(emacs-session-id . 1)(output . ((id . "9469176874988818267")(mode . hiragana)(consumed . t)(preedit . ((cursor . 1)(segment ((annotation . underline)(value . "あ")(value-length . 1)(key . "あ")))))(candidates . ((size . 1)(candidate ((index . 0)(value . "あ")(annotation . ((description . "ひらがな")))(id . 0)))(position . 0)(category . suggestion)(display-type . main)(footer . ((label . "Tabキーで選択")))))(status . ((activated . t)(mode . hiragana)(comeback-mode . hiragana)))(all-candidate-words . ((candidates ((id . 0)(index . 0)(value . "あ")(annotation . ((description . "ひらがな")))))(category . suggestion)))))) $
init.elに以下を追記します。
;; (require 'mozc) (load "~/src/mozc/src/unix/emacs/mozc.el") (setq default-input-method "japanese-mozc") ;; exec-pathが通っていれば不要 (setq mozc-helper-program-name "~/src/mozc/src/out_mac/Release/mozc_emacs_helper")
C-\ で日本語入力が切り替わるはずです。
動作確認ができたら mozc.el, mozc_emacs_helper をそれぞれ load-path, exec-path の通った場所に置いてください。
mozc.elを使ったモードレス日本語入力インタフェース、ac-mozc を作っています。 良かったらこちらも試してみてください。
この手順でビルドできない方がいたので、別の方法を試してみました。
((Rで) 書く (Lisp) インタプリタ)の続きです。
以前の記事を見た@kohskeさんから、 環境はRの環境オブジェクトを使えば良いのでは、とアドバイスを頂きました。
やってみたら自前で環境を実装しなくて良い分簡潔になったし、より面白い使い方ができるようになりました。
前回同様Gistに上げておきました。 変なところがあったら教えてください。
主な変更点は
前回と同様です。
Rインタプリタを起動してコードを読み込ませます。
repl() を実行するとLispの対話式インタプリタが起動します。
$ ls
lispr.R
$ R -q
> source("lispr.R")
> repl()
lispr> (+ 1 2)
3
lispr> (define add2 (lambda (x) (+ x 2)))
#<closure>
lispr> (add2 40)
42
lispr>
関数 repl の引数 parent に渡した環境がLispの環境の親になります。(デフォルトだとRのグローバル環境)
よって今回はLispの環境からRの環境を参照できるので、LispでRの関数が使えます。
lispr> (: 1 10) 1 2 3 4 5 6 7 8 9 10 lispr> (rnorm 3) 0.536481224524994 -0.547993231580984 -2.14041393248752 lispr> (seq 0 10 2) 0 2 4 6 8 10 lispr> (begin (plot cars) (lines (lowess cars)) 1) 1 lispr>
S式でRを使える!楽しい!
やはり言語処理系を作るのは楽しいです。
最近Rubyを始めました。
手始めにLispインタプリタを書いてみます。
元ねたはPeter Norvigの (How to Write a (Lisp) Interpreter (in Python)) (日本語訳: ((Pythonで) 書く (Lisp) インタプリタ))です。
(ちなみに以前、Rでも同じことをやりました: ((Rで) 書く (Lisp) インタプリタ))
Gistに上げておきました。 変なところがあったら教えてください。
$ ruby lisp.rb lisp.rb> (+ 1 2 3) 6 lisp.rb> (define add2 (lambda (x) (+ x 2))) #<Proc:0x00000001647958@lisp.rb:62 (lambda)> lisp.rb> (add2 40) 42 lisp.rb> (define map (lambda (f l) (if (null? l) (quote ()) (cons (f (car l)) (map f (cdr l)))))) #<Proc:0x0000000164f1a8@lisp.rb:62 (lambda)> lisp.rb> (map add2 (list 10 20 30)) (12 22 32) lisp.rb>
Rubyを使ってみて思ったことをメモしておきます。
Perlっぽい
Lisp(関数型)っぽい
オブジェクト指向
割と良い感じです。もうちょっと使ってみます。 ワンライナーとかちょっとしたスクリプトとかPerlのかわりに使ってみようかな。
同じことをやっている方は他にもいます。
元ねたのページ のコメントで紹介されていた
以下の実装が簡潔で素敵です。
わからないところはこちらをチラ見しながら作りました。
その後少し手を加えて、REPLで式の途中に改行を入れられるようにしました。
(上に貼ってあるGistは修正後です。)
こんな感じに入力できます。
lisp.rb> (+ (* 3
(+ (* 2 4)
(+ 3 5)))
(+ (- 10 7)
6))
57
lisp.rb>
思ったより少ない変更で実現できました。 (Gistの履歴)
前回の続きです。
今回はRCLを使って、Common LispからRの関数を呼んでグラフを描いてみます。
こちらに書いてある通り、Quicklispでインストールできました。
> (ql:quickload :rcl)
詳しいマニュアルは無いみたいです。
RCL examples に短いサンプル、 Comparing RCL with Rpy にRPyとの比較があります。
あとインストール先の examples/ 以下にサンプルコードがいくつかあります。
サンプルコードを参考にしながら何となく書いてみました。
(asdf:oos 'asdf:load-op :rcl)
(r:r-init)
(r:enable-rcl-syntax)
(defun plot-num-of-animals (animal-state)
(let ((day (mapcar #'car animal-state))
(num (mapcar (lambda (x) (length (cadr x))) animal-state)))
[plot day num :type "o" :pch 20 :ylim [c 0 [max num]]
:main "動物の個体数" :xlab "経過日数" :ylab "動物の個体数"]))
(defun plot-hist (animal-state)
(let ((max-x 1.0)
(max-y 160))
(mapc (lambda (state)
(let ((day (car state))
(rate (cadr state)))
[hist rate :breaks [seq 0 max-x 0.02]
:ylim [c 0 max-y] :main (format nil "~7d 日後" day)
:col "gray" :xlab "直進率" :ylab "動物の個体数"]))
animal-state)))
(defun animal-state->png (out-dir animal-state)
(r:with-device ((format nil "~A/%03d" out-dir) :png :width 400 :height 300)
(plot-num-of-animals animal-state)
(plot-hist animal-state)))
角括弧[] の部分でRの関数を呼んでいます。
Lispのコードと混ぜて書けるのがおもしろいです。
あと、r:with-device で描画のコードを包むのがLispっぽくて好きです。
(Rだと デバイス開く、描画、デバイス閉じる、と手続き的)
描画を実行します。
まずは前回同様、20万日分シミュレーションを走らせ、1万日間隔で動物の状態をdumpします。
> (defparameter *dump* (dump-animal-state 200000 10000))
グラフを描画します。
> (animal-state->png "Rplot" *dump*)
Rplot/ 以下に連番のpngファイルが生成されます。
前回同様のグラフができました。


今回試した範囲では割と良い感じに使えました。 Rに慣れた人が、Common Lispでデータをいじっていて、ちょっとグラフを描いて確かめたい、 みたいなときに便利かも。
ちなみにCommon Lispでグラフを描く方法は他にもいろいろあるみたいです。 (CLiki: plotting)
Land of Lisp の10章で進化シミュレーションを実装します。
こんな感じ。
* が草で M が動物です。
ちなみに翻訳者のShiro氏が、遺伝子の傾向の違いを色で表示する版のGaucheのコードを公開しています。
(Island Life - GaucheでもLand of Lisp)
ところでシミュレーションを続けると、行動パターンが異なる2つの種に進化します。
面白いですね。
この種の分化がどのように進むのか気になったので、Rを使ってグラフ化してみます。
進化シミュレーションのコードは公式ページで公開されています。(evolution.lisp)
動物の構造体の中身はこんな感じ。
#S(ANIMAL :X 50 :Y 15 :ENERGY 114 :DIR 0 :GENES (5 4 10 9 5 5 9 10))
genes フィードが遺伝子情報で、動物の行動パターンを決定します。
8つの整数は動物が8方向どちらに向きを変えやすいかを表します。
先頭 (スロット 0) の値が大きければその動物は向きを変えずに直進しやすく、
次 (スロット 1) の値が大きければ時計回りに45度向きを変えやすい、といった感じです。
動物の性質を表すために、 直進率 という指標を考えました。これは動物がまっすぐ進む確率です。 直進率が高い = 長距離を移動する = ロバ、直進率が低い = うろうろする = ゾウ、と考えて良いですかね。
動物の直進率を計算する straight-rate 関数:
(defun straight-rate (animal)
(let ((genes (animal-genes animal)))
(/ (car genes)
(apply #'+ genes))))
進化の過程を知りたいので、一定間隔で動物たちの直進率をdumpします。
(defun dump-animal-state (days by)
(loop for i
from 1
to days
do (update-world)
if (zerop (mod i by))
collect (list i
(mapcar #'straight-rate *animals*))))
days で指定した日数分シミュレーションを走らせ、by で指定した間隔で全動物の直進率を計算します。
この関数は (経過日数 全動物の直進率のリスト) のリストを返します。
3日間シミュレーションを走らせて1日間隔でdumpする例:
> (defparameter *dump* (dump-animal-state 3 1)) *DUMP* > *dump* ((1 (5/23 5/23)) (2 (1/5 1/5 5/23 5/23)) (3 (5/23 5/23 1/5 1/5 1/5 1/5 5/23 5/23)))
指定期間の動物の状態を計算できるようになりましたが、 Common LispとRの間でどうやってデータをやり取りしましょう。
今回はCommon Lisp側でS式をRのデータ表現に変換することにしました。 R側はそれをevalするだけなので楽です。evalは危険だけどこういう時は手軽で便利ですね。
animal-state->r 関数は動物の状態のリストをRのデータ表現に変換します。
(defun animal-state->r (animal-state)
(format nil "list(~{~a~^,~% ~})~%"
(mapcar (lambda (x)
(format nil
"list(day=~a, straightRate=c(~{~f~^, ~}))"
(car x)
(cadr x)))
animal-state)))
先ほどの *dump* を変換してみます。
> (animal-state->r *dump*)
"list(list(day=1, straightRate=c(0.2173913, 0.2173913)),
list(day=2, straightRate=c(0.2, 0.2, 0.2173913, 0.2173913)),
list(day=3, straightRate=c(0.2173913, 0.2173913, 0.2, 0.2, 0.2, 0.2, 0.2173913, 0.2173913)))
"
ファイルに書き出す関数:
(defun write-animal-state (fname animal-state)
(with-open-file (my-stream
fname
:direction :output
:if-exists :supersede)
(princ (animal-state->r animal-state)
my-stream)))
では実際にシミュレーションを走らせて、結果をファイルに書き出します。
> (load "evolution") T > (write-animal-state "animal-state.R" (dump-animal-state 200000 10000))
20万日分シミュレーションを走らせ、1万日間隔で animal-state.R というファイルに書き出しました。
ちなみにdump前に (load "evolution") を実行しているのは世界をリセットするためです。
オリジナルのコードに手を入れずに手っ取り早く世界をリセットする方法が他に思いつきませんでした...
Rでグラフを描画します。
plot-evolution.R
stateFile <- "animal-state.R"
stateList <- eval(parse(stateFile))
outDir <- "Rplot"
png(filename=file.path(outDir, "%03d.png"), width=400, height=300)
numTable <- data.frame(t(sapply(stateList,
function(x) {
c(day=x[["day"]],
num=length(x[["straightRate"]]))
})))
plot(numTable, type="o", pch=20, ylim=c(0, max(numTable[, 2])),
main="動物の個体数", xlab="経過日数", ylab="動物の個体数")
maxX <- 1.0
maxY <- 160
for (state in stateList) {
hist(state[["straightRate"]], breaks=seq(0, maxX, 0.02), ylim=c(0, maxY),
main=sprintf("%7d 日後", state[["day"]]), col="gray",
xlab="直進率", ylab="動物の個体数")
}
dev.off()
このRスクリプトを実行します。
$ mkdir Rplot $ Rscript --vanilla plot-evolution.R
Rplot/ 以下に連番のpngファイルが生成されます。
まずは動物の個体数の遷移です。

個体数は160前後で安定しています。これは植物が生える速度が常に一定のため、世界が平衡状態を保っているということでしょうか。
次に動物の直進率と個体数のヒストグラムを見てみます。
1万日後。まだ同じ傾向の動物しかいません。

3万日後。目立った変化無し。

4万日後。種の分化が始まった!

5万日後。完全に分かれました。
14万日後。ロバの直進率がさらに上がっています。
他の手法を試してみました: Common LispでR (RCLを使ってみる)