tag:blogger.com,1999:blog-30975957641434087422024-03-14T17:19:45.584+09:00入口と出口igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-3097595764143408742.post-57645356698357520532014-12-18T22:53:00.000+09:002014-12-21T19:01:06.387+09:00「このEmacs Lispを使っている人はこんなEmacs Lispも使っています」がわかるwebサービス、el-moreを作っています<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSHUqO2yr2ptXyu7XA8KCHue1aU2PgBpPTY6HRTtI5KPIv1KKoVe4-NrQuXdyBZRZrf2OJYoz3S_snqMXkirD2SAHY84r7DhyV1xmkj1hRQzVlulbW7oVp6x__lcb3xXZnYjHRuMsiApMx/s1600/top.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSHUqO2yr2ptXyu7XA8KCHue1aU2PgBpPTY6HRTtI5KPIv1KKoVe4-NrQuXdyBZRZrf2OJYoz3S_snqMXkirD2SAHY84r7DhyV1xmkj1hRQzVlulbW7oVp6x__lcb3xXZnYjHRuMsiApMx/s400/top.png" /></a></p>
<p>これは <a href="http://qiita.com/advent-calendar/2014/emacs">Emacs Advent Calendar 2014</a> の18日目の記事です。</p>
<p>Emacs Lispパッケージをおすすめするwebサービス、<strong>el-more</strong> を作っています。
「このEmacs Lispを使っている人はこんなEmacs Lispも使っています」がわかります。</p>
<p>現在、Herokuで動いています。</p>
<ul>
<li><a href="https://el-more.herokuapp.com/">https://el-more.herokuapp.com/</a></li>
</ul>
<h2>このEmacs Lispを使っている人はこんなEmacs Lispも使っています</h2>
<p><a href="http://el-more.herokuapp.com/packages/596">expand-region</a> を使っている人は
<a href="http://el-more.herokuapp.com/packages/1295">multiple-cursors</a> や
<a href="http://el-more.herokuapp.com/packages/2114">yasnippet</a> も使っているようです。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2CYanT55qV5RwF71t4_-H5gW6MXXo93zAo-AW2Nf9Bi6TkoHVG3KlDtJRep5xBSgo2QttoBNNwfaXDKTQk0hwch9rqSZwzxN8JSz6mJbJV-bL4TyONv510KIKQqZwlehBTKcrGOnItGJo/s1600/expand-region.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2CYanT55qV5RwF71t4_-H5gW6MXXo93zAo-AW2Nf9Bi6TkoHVG3KlDtJRep5xBSgo2QttoBNNwfaXDKTQk0hwch9rqSZwzxN8JSz6mJbJV-bL4TyONv510KIKQqZwlehBTKcrGOnItGJo/s400/expand-region.png" /></a></p>
<p><a href="http://el-more.herokuapp.com/packages/2108">yaml-mode</a> を使っている人は
<a href="http://el-more.herokuapp.com/packages/1210">markdown-mode</a> や
<a href="http://el-more.herokuapp.com/packages/258">coffee-mode</a> みたいな言語用のmajor-modeも使っているようです。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQWf3BsFidwwvg-WRx3UMNgvk_QdPVj158E1eiXJIiE8zyHsAfjIfZ9lATUybySMqNMsx8aY4YEkuiROYnhc1jx2Slp_SQXVA715p9tuAt48gjyXBex9qBNb6Res1NpiVGQ34d2r6Gy2n9/s1600/yaml-mode.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQWf3BsFidwwvg-WRx3UMNgvk_QdPVj158E1eiXJIiE8zyHsAfjIfZ9lATUybySMqNMsx8aY4YEkuiROYnhc1jx2Slp_SQXVA715p9tuAt48gjyXBex9qBNb6Res1NpiVGQ34d2r6Gy2n9/s400/yaml-mode.png" /></a></p>
<p>おもしろいですね。</p>
<p>みなさんもお気に入りのEmacs Lispのページを見てみてください。知らなかった素敵なEmacs Lispが見つかるかもしれません。</p>
<h2>しくみ</h2>
<ul>
<li>GitHubで公開されているCaskファイルを検索 (<a href="https://github.com/search?q=filename%3Acask+depends-on&type=Code">例</a>)。
これで誰がどのEmacs Lispパッケージを使っているかがわかります。</li>
<li><a href="http://melpa.org/">MELPA</a> からEmacs Lispパッケージの情報を取得します。</li>
<li>パッケージどうしの類似度 (この場合は一緒にインストールされる確率) を計算します。</li>
</ul>
<h2>実装</h2>
<p>Ruby on Railsで作りました。</p>
<p>Herokuで動いています。Herokuで無料で使えるのは</p>
<ul>
<li>DB (Heroku Postgres) 10000行</li>
<li>key-value store (Redis Cloud) 25MB</li>
</ul>
<p>とかで、データ量をこれ以下に抑えるために泣く泣く集計対象のユーザ数を絞っています。(現在は100人)</p>
<h2>ソースコード</h2>
<p>ソースコードはGitHubにあります。</p>
<ul>
<li><a href="https://github.com/igjit/el-more">igjit/el-more</a></li>
</ul>
<h2>おわりに</h2>
<p>公開したばかりでまだまだ未完成だと思います。</p>
<p>問題点、改善案、疑問、使ってみた感想など、何でも気軽にご連絡ください (<a href="https://twitter.com/igjit">Twitter</a>)。</p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-24081843044323987072014-09-02T22:24:00.000+09:002014-09-02T22:24:43.100+09:00MacのEmacsでmozc.elを使う (mozc-serverをVagrantで動かす)<p><a href="http://igjit.blogspot.com/2014/04/mac-emacs-mozc.html">前回</a> 、MacのEmacsでmozc.elを使うために、mozc-serverをビルドする手順を紹介しました。しかしその手順でビルドできない方がいたので、別の方法を試してみます。</p>
<p>今回はmozc-serverを仮想マシンで動かします。</p>
<ul>
<li>Vagrant</li>
<li>VirtualBox</li>
</ul>
<p>が必要です。</p>
<h2>手順</h2>
<ul>
<li><a href="https://github.com/igjit/vagrant-emacs-mozc">igjit/vagrant-emacs-mozc</a></li>
</ul>
<h2>結果</h2>
<p>mozc.elが動きました。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8m0DmTnZcAOTwWthprtefGwEVFCMd9UL11ds3UwV0jGZ3foybffG9KyKjwZxUQpua-q8VJ9qFYKC-Q1JNkd3MsI9ilhBRdmcaPdHXRbHgLCCocCnnDE7uOHwwH89Ue6lRE8A7McxrgnVB/s1600/mozc-el.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8m0DmTnZcAOTwWthprtefGwEVFCMd9UL11ds3UwV0jGZ3foybffG9KyKjwZxUQpua-q8VJ9qFYKC-Q1JNkd3MsI9ilhBRdmcaPdHXRbHgLCCocCnnDE7uOHwwH89Ue6lRE8A7McxrgnVB/s400/mozc-el.png" /></a></p>
<p>mozc.elが動けば<a href="https://github.com/igjit/ac-mozc">ac-mozc</a>も動くはずです。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb0Y2FGIkr4LASgDyhYFOQjrCgqiYApyiSQwcoixIABA5kXWKvfqIXxg_boHk9bc4HsP7-Hu93Hl3mlA9bskVpaOYel-rsB9Q0ZdEJa1b0cpT4jOGdebhQMAUf_dMOSKaFYGx9K-cu8zkT/s1600/ac-mozc.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb0Y2FGIkr4LASgDyhYFOQjrCgqiYApyiSQwcoixIABA5kXWKvfqIXxg_boHk9bc4HsP7-Hu93Hl3mlA9bskVpaOYel-rsB9Q0ZdEJa1b0cpT4jOGdebhQMAUf_dMOSKaFYGx9K-cu8zkT/s400/ac-mozc.png" /></a></p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-70864813684300362552014-04-17T23:36:00.000+09:002014-09-02T22:38:22.020+09:00MacのEmacsでmozc.elを使う (Mozcのビルド)<p><a href="http://code.google.com/p/mozc/">Mozc</a>は、<a href="http://www.google.co.jp/ime/">Google 日本語入力</a>のオープンソース版のIMEです。
そしてmozc.elは、Mozcを使ってEmacsで日本語入力するためのEmacs Lispです。</p>
<p>今回は、Mac上のEmacsでmozc.elを使って日本語入力できるようにします。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGE7vrWKVbaqv2zZgUTjvdeb9jpmFlMgqTXULf2Nx50FZsYQ4WlsIwGNOVpSUWMNhkEjy1NRCO8dKM_Tz6nG-lGIppgq32w6xdDpkADTz4f1-S5W9LW9gwZo9iDmy5oEHaACQ8kNb4se9w/s1600/mozc-el.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGE7vrWKVbaqv2zZgUTjvdeb9jpmFlMgqTXULf2Nx50FZsYQ4WlsIwGNOVpSUWMNhkEjy1NRCO8dKM_Tz6nG-lGIppgq32w6xdDpkADTz4f1-S5W9LW9gwZo9iDmy5oEHaACQ8kNb4se9w/s400/mozc-el.png" /></a></p>
<p>EmacsとMozcは以下のような感じで通信しているみたいです。</p>
<p><?prettify?></p>
<pre class="prettyprint">
[Emacs + mozc.el] <-- S式 --> [mozc_emacs_helper] <-- IPC --> [Mozc server]
</pre>
<p>Emacsと<code>Mozc server</code>が通信するのに<code>mozc_emacs_helper</code>が必要ですが、公式にはMac上でのビルドに対応していません。
なのでビルド用のスクリプトを<a href="https://github.com/igjit/mac-emacs-mozc/commit/8a5bb829ab7b1a23f36335605162d7a1d2af9536">ちょっといじって</a>、ビルドできるようにしました。</p>
<ul>
<li>GitHub: <a href="https://github.com/igjit/mac-emacs-mozc">igjit/mac-emacs-mozc</a></li>
</ul>
<h2>要件</h2>
<p>公式の<a href="http://code.google.com/p/mozc/wiki/MacBuildInstructions">MacBuildInstructions</a>には</p>
<ul>
<li>システム要件
<ul>
<li>OSX 10.5 or later intel only</li>
</ul></li>
<li>ソフトウェア要件
<ul>
<li>Xcode</li>
<li>Qt 4.6.3 or later (optional)</li>
</ul></li>
</ul>
<p>とあります。Qtはオプションということなので今回は無しでビルドします。</p>
<p>私は OS X 10.9.2 + Xcode 5.1.1 で実行しました。</p>
<h2>ビルド手順</h2>
<p>詳細は公式の<a href="http://code.google.com/p/mozc/wiki/MacBuildInstructions">MacBuildInstructions</a>も参照してください。</p>
<p>ソースコードの取得
<?prettify?></p>
<pre class="prettyprint">
$ 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
</pre>
<p><code>gclient sync</code>で</p>
<pre><code>Error: Command svn checkout https://src.chromium.org/chrome/trunk/src/tools/clang/scripts@171017 ...
</code></pre>
<p>みたいなエラーが出ましたが気にしないことにします。</p>
<p><code>build_mozc.py</code>を上書きします。
<?prettify?></p>
<pre class="prettyprint">
$ cd ~/src/mozc/src
$ curl -O https://raw.githubusercontent.com/igjit/mac-emacs-mozc/master/build_mozc.py
</pre>
<p>ビルドの実行
<?prettify?></p>
<pre class="prettyprint">
$ 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
</pre>
<p>インストールします。
<?prettify?></p>
<pre class="prettyprint">
$ 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
</pre>
<p>ここで一旦GUIをログアウトします。
再ログイン後にMozcが使えるようになります。</p>
<p>動作確認
<?prettify?></p>
<pre class="prettyprint">
$ 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))))))
$
</pre>
<h2>Emacsの設定</h2>
<p>init.elに以下を追記します。</p>
<p><?prettify?></p>
<pre class="prettyprint">
;; (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")
</pre>
<p><code>C-\</code> で日本語入力が切り替わるはずです。
動作確認ができたら <code>mozc.el</code>, <code>mozc_emacs_helper</code> をそれぞれ <code>load-path</code>, <code>exec-path</code> の通った場所に置いてください。</p>
<h2>See also</h2>
<p>mozc.elを使ったモードレス日本語入力インタフェース、<a href="https://github.com/igjit/ac-mozc">ac-mozc</a> を作っています。
良かったらこちらも試してみてください。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL7cgjzANF2VpsLra4MQ3K8roxEmLlgD6AfT9CMCPzVyaJovETnVyeu-j4CUyVBv6wG-IUudDR-4gOR_62FXNxmGy7WsEFJVloimGN6Um2h_CTEVV0tI5EC21WS4y8zpGr3ZREhFc-yUD0/s1600/ac-mozc.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL7cgjzANF2VpsLra4MQ3K8roxEmLlgD6AfT9CMCPzVyaJovETnVyeu-j4CUyVBv6wG-IUudDR-4gOR_62FXNxmGy7WsEFJVloimGN6Um2h_CTEVV0tI5EC21WS4y8zpGr3ZREhFc-yUD0/s400/ac-mozc.png" /></a></p>
<h2>(追記)</h2>
<p>この手順でビルドできない方がいたので、別の方法を試してみました。</p>
<p><a href="http://igjit.blogspot.jp/2014/09/vagrant-emacs-mozc.html">MacのEmacsでmozc.elを使う (mozc-serverをVagrantで動かす)</a></p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-59022769441074313212013-11-10T16:42:00.000+09:002013-11-10T16:43:05.095+09:00((Rで) 書く ((もっとRっぽい) Lisp) インタプリタ)<p><a href="http://igjit.blogspot.com/2013/05/lisp-r.html">((Rで) 書く (Lisp) インタプリタ)</a>の続きです。</p>
<p>以前の記事を見た<a href="https://twitter.com/kohske/">@kohske</a>さんから、
環境はRの環境オブジェクトを使えば良いのでは、とアドバイスを頂きました。</p>
<p>やってみたら自前で環境を実装しなくて良い分簡潔になったし、より面白い使い方ができるようになりました。</p>
<h2>コード</h2>
<p>前回同様Gistに<a href="https://gist.github.com/igjit/7276203">上げておきました</a>。
変なところがあったら教えてください。</p>
<script src="https://gist.github.com/igjit/7276203.js"></script>
<p>主な変更点は</p>
<ul>
<li>Rの環境オブジェクトを流用</li>
<li>Lispの関数の呼び出し方法を変更: proc(exps) から do.call(proc, exps) に</li>
</ul>
<h2>遊び方</h2>
<p>前回と同様です。</p>
<p>Rインタプリタを起動してコードを読み込ませます。 <br />
<code>repl()</code> を実行するとLispの対話式インタプリタが起動します。</p>
<p><?prettify?></p>
<pre class="prettyprint">
$ 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>
</pre>
<p>関数 <code>repl</code> の引数 <code>parent</code> に渡した環境がLispの環境の親になります。(デフォルトだとRのグローバル環境) <br />
よって今回はLispの環境からRの環境を参照できるので、<strong>LispでRの関数が使えます。</strong></p>
<p><?prettify?></p>
<pre class="prettyprint">
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>
</pre>
<p>S式でRを使える!楽しい!</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlkpJwh_ss9fZP9celqHScozgH_IZyRRvVcyGg7ciiQgFvnIQEXgRXDvBOp1gIUeOSD-wHyeQRHuNLY4ffnrm5l5R1qrOqksKprH7bIKYUC97sLispHv-YtRbP4Ynu6pl07_xecdYh3wRL/s1600/lispr-plot.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlkpJwh_ss9fZP9celqHScozgH_IZyRRvVcyGg7ciiQgFvnIQEXgRXDvBOp1gIUeOSD-wHyeQRHuNLY4ffnrm5l5R1qrOqksKprH7bIKYUC97sLispHv-YtRbP4Ynu6pl07_xecdYh3wRL/s400/lispr-plot.png" /></a></p>
<h2>感想</h2>
<p>やはり言語処理系を作るのは楽しいです。</p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-29310347710324875542013-08-09T08:40:00.000+09:002013-09-14T11:07:30.263+09:00((Rubyで) 書く (Lisp) インタプリタ)<p>最近Rubyを始めました。</p>
<p>手始めにLispインタプリタを書いてみます。</p>
<p>元ねたはPeter Norvigの <a href="http://norvig.com/lispy.html">(How to Write a (Lisp) Interpreter (in Python))</a>
(日本語訳: <a href="http://www.aoky.net/articles/peter_norvig/lispy.htm">((Pythonで) 書く (Lisp) インタプリタ)</a>)です。</p>
<p>(ちなみに以前、Rでも同じことをやりました: <a href="http://igjit.blogspot.com/2013/05/lisp-r.html">((Rで) 書く (Lisp) インタプリタ)</a>)</p>
<h2>コード</h2>
<p>Gistに<a href="https://gist.github.com/igjit/6189716">上げておきました</a>。
変なところがあったら教えてください。</p>
<script src="https://gist.github.com/igjit/6189716.js"></script>
<h2>遊び方</h2>
<p><?prettify?></p>
<pre class="prettyprint">
$ 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>
</pre>
<h2>感想</h2>
<p>Rubyを使ってみて思ったことをメモしておきます。</p>
<ul>
<li><p>Perlっぽい</p>
<ul>
<li>メソッドのかっこを省略できる</li>
<li>ifとかwhileを後置できる</li>
</ul></li>
<li><p>Lisp(関数型)っぽい</p>
<ul>
<li>Symbol</li>
<li>いろんなものが値を返す(ifとか)</li>
<li>returnを省略できる</li>
</ul></li>
<li><p>オブジェクト指向</p>
<ul>
<li>何でもオブジェクト!</li>
<li>mapとかの高階関数がメソッドなのはなんだか違和感があるけど、
メソッドチェインができるのは良いかも。</li>
</ul></li>
</ul>
<p>割と良い感じです。もうちょっと使ってみます。
ワンライナーとかちょっとしたスクリプトとかPerlのかわりに使ってみようかな。</p>
<h2>参考文献</h2>
<p>同じことをやっている方は他にもいます。 <br />
<a href="http://norvig.com/lispy.html">元ねたのページ</a> のコメントで紹介されていた
以下の実装が簡潔で素敵です。
わからないところはこちらをチラ見しながら作りました。</p>
<ul>
<li><a href="http://stuff.thedeemon.com/rispy/">Index of /rispy</a></li>
</ul>
<h2>(追記)</h2>
<p>その後少し手を加えて、REPLで式の途中に改行を入れられるようにしました。 <br />
(上に貼ってあるGistは修正後です。)</p>
<p>こんな感じに入力できます。</p>
<p><?prettify?></p>
<pre class="prettyprint">
lisp.rb> (+ (* 3
(+ (* 2 4)
(+ 3 5)))
(+ (- 10 7)
6))
57
lisp.rb>
</pre>
<p>思ったより少ない変更で実現できました。
(<a href="https://gist.github.com/igjit/6189716/revisions">Gistの履歴</a>)</p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-45222992940774554642013-07-22T00:58:00.000+09:002013-07-22T00:58:52.529+09:00Common LispでR (RCLを使ってみる)<p><a href="http://igjit.blogspot.com/2013/06/evolution-r.html">前回</a>の続きです。</p>
<p>今回は<a href="http://common-lisp.net/project/rcl/">RCL</a>を使って、Common LispからRの関数を呼んでグラフを描いてみます。</p>
<h2>インストール</h2>
<p><a href="http://common-lisp.net/project/rcl/">こちら</a>に書いてある通り、<a href="http://www.quicklisp.org/">Quicklisp</a>でインストールできました。</p>
<p><?prettify?></p>
<pre class="prettyprint">
> (ql:quickload :rcl)
</pre>
<h2>使い方</h2>
<p>詳しいマニュアルは無いみたいです。</p>
<p><a href="http://common-lisp.net/project/rcl/examples.html">RCL examples</a> に短いサンプル、
<a href="http://common-lisp.net/project/rcl/rpy.html">Comparing RCL with Rpy</a> に<a href="http://rpy.sourceforge.net/">RPy</a>との比較があります。</p>
<p>あとインストール先の <code>examples/</code> 以下にサンプルコードがいくつかあります。</p>
<h2>グラフ描画のコード</h2>
<p>サンプルコードを参考にしながら何となく書いてみました。</p>
<p><?prettify?></p>
<pre class="prettyprint">
(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)))
</pre>
<p>角括弧<code>[]</code> の部分でRの関数を呼んでいます。
Lispのコードと混ぜて書けるのがおもしろいです。</p>
<p>あと、<code>r:with-device</code> で描画のコードを包むのがLispっぽくて好きです。
(Rだと デバイス開く、描画、デバイス閉じる、と手続き的)</p>
<h2>描画</h2>
<p>描画を実行します。</p>
<p>まずは前回同様、20万日分シミュレーションを走らせ、1万日間隔で動物の状態をdumpします。</p>
<p><?prettify?></p>
<pre class="prettyprint">
> (defparameter *dump* (dump-animal-state 200000 10000))
</pre>
<p>グラフを描画します。</p>
<p><?prettify?></p>
<pre class="prettyprint">
> (animal-state->png "Rplot" *dump*)
</pre>
<p><code>Rplot/</code> 以下に連番のpngファイルが生成されます。</p>
<p>前回同様のグラフができました。</p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUPDCU-h6-CHOvlTXxz9Uc1MyQBTurLLwB7rpTWLULZ_BBMIYjPErHJIAyvpmJrkwYZOB6D837yJu_mDiCHzeM8Yi8a2AH2sCJqZbfls5iWasg2e8L5bcJmEKVxP6wMdz7OZBX-LFp09If/s400/001.png" /></p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0Ty8uBLUpo2nJqb-D307ybTpPD6fsvkhi7OBmggnM3JyWXXKBlTuhwpbyc8uRqWF0xy8JiTkQwGhO5pqIaNCJMq1R0KqgMXKKFdHEfs1WCaFRYx_E1K67ZZb4B3FeV3gpo4M5K-kUPImp/s400/017.png" /></p>
<h2>感想</h2>
<p>今回試した範囲では割と良い感じに使えました。
Rに慣れた人が、Common Lispでデータをいじっていて、ちょっとグラフを描いて確かめたい、
みたいなときに便利かも。</p>
<p>ちなみにCommon Lispでグラフを描く方法は他にもいろいろあるみたいです。
(<a href="http://www.cliki.net/plotting">CLiki: plotting</a>)</p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-74455369870287240482013-06-09T22:07:00.000+09:002013-07-22T01:32:22.949+09:00Land of Lispの進化シミュレーションの様子をRでグラフ化する<p><a href="http://www.oreilly.co.jp/books/9784873115870/">Land of Lisp</a> の10章で進化シミュレーションを実装します。</p>
<p>こんな感じ。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxKATxHpTfBNDKCrLYvaoGPM_1uARAERe5cpTnVJrZXNI3C3TJ17uZth8FQH1CsotxAfHH9YclNbwdumBJ6tqWmJ2eXsARjuDZryszR75mNjwh_KeiXek-vY_4RwWmwqFgxQP3B_YqFM6m/s1600/terminal.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxKATxHpTfBNDKCrLYvaoGPM_1uARAERe5cpTnVJrZXNI3C3TJ17uZth8FQH1CsotxAfHH9YclNbwdumBJ6tqWmJ2eXsARjuDZryszR75mNjwh_KeiXek-vY_4RwWmwqFgxQP3B_YqFM6m/s320/terminal.png" /></a></p>
<p><code>*</code> が草で <code>M</code> が動物です。 <br />
ちなみに翻訳者のShiro氏が、遺伝子の傾向の違いを色で表示する版のGaucheのコードを公開しています。
(<a href="http://blog.practical-scheme.net/shiro/20130223-land-of-gauche">Island Life - GaucheでもLand of Lisp</a>)</p>
<p>ところでシミュレーションを続けると、行動パターンが異なる2つの種に進化します。</p>
<ul>
<li>ゾウ : ジャングル(画面中央部)の豊富な食物に集中する。ジャングルから離れないように周りをうろうろする。</li>
<li>ロバ : 乾燥帯(ジャングル以外の部分)で食物を探し回る。広い範囲を移動する。</li>
</ul>
<p>面白いですね。</p>
<p>この種の分化がどのように進むのか気になったので、Rを使ってグラフ化してみます。</p>
<h2>動物の遺伝子</h2>
<p>進化シミュレーションのコードは公式ページで<a href="http://landoflisp.com/source.html">公開</a>されています。(evolution.lisp)</p>
<p>動物の構造体の中身はこんな感じ。</p>
<p><?prettify?></p>
<pre class="prettyprint">
#S(ANIMAL :X 50 :Y 15 :ENERGY 114 :DIR 0 :GENES (5 4 10 9 5 5 9 10))
</pre>
<p><code>genes</code> フィードが遺伝子情報で、動物の行動パターンを決定します。
8つの整数は動物が8方向どちらに向きを変えやすいかを表します。
先頭 (スロット 0) の値が大きければその動物は向きを変えずに直進しやすく、
次 (スロット 1) の値が大きければ時計回りに45度向きを変えやすい、といった感じです。</p>
<h2>ゾウ? それともロバ?</h2>
<p>動物の性質を表すために、 <strong>直進率</strong> という指標を考えました。これは動物がまっすぐ進む確率です。
直進率が高い = 長距離を移動する = ロバ、直進率が低い = うろうろする = ゾウ、と考えて良いですかね。</p>
<p>動物の直進率を計算する <code>straight-rate</code> 関数:</p>
<p><?prettify?></p>
<pre class="prettyprint">
(defun straight-rate (animal)
(let ((genes (animal-genes animal)))
(/ (car genes)
(apply #'+ genes))))
</pre>
<h2>動物の状態をdump</h2>
<p>進化の過程を知りたいので、一定間隔で動物たちの直進率をdumpします。</p>
<p><?prettify?></p>
<pre class="prettyprint">
(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*))))
</pre>
<p><code>days</code> で指定した日数分シミュレーションを走らせ、<code>by</code> で指定した間隔で全動物の直進率を計算します。 <br />
この関数は <code>(経過日数 全動物の直進率のリスト)</code> のリストを返します。</p>
<p>3日間シミュレーションを走らせて1日間隔でdumpする例:</p>
<p><?prettify?></p>
<pre class="prettyprint">
> (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)))
</pre>
<h2>Rにデータを渡す</h2>
<p>指定期間の動物の状態を計算できるようになりましたが、
Common LispとRの間でどうやってデータをやり取りしましょう。</p>
<p>今回はCommon Lisp側でS式をRのデータ表現に変換することにしました。
R側はそれをevalするだけなので楽です。evalは危険だけどこういう時は手軽で便利ですね。</p>
<p><code>animal-state->r</code> 関数は動物の状態のリストをRのデータ表現に変換します。</p>
<p><?prettify?></p>
<pre class="prettyprint">
(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)))
</pre>
<p>先ほどの <code>*dump*</code> を変換してみます。</p>
<p><?prettify?></p>
<pre class="prettyprint">
> (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)))
"
</pre>
<p>ファイルに書き出す関数:</p>
<p><?prettify?></p>
<pre class="prettyprint">
(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)))
</pre>
<p>では実際にシミュレーションを走らせて、結果をファイルに書き出します。</p>
<p><?prettify?></p>
<pre class="prettyprint">
> (load "evolution")
T
> (write-animal-state "animal-state.R" (dump-animal-state 200000 10000))
</pre>
<p>20万日分シミュレーションを走らせ、1万日間隔で <code>animal-state.R</code> というファイルに書き出しました。</p>
<p>ちなみにdump前に <code>(load "evolution")</code> を実行しているのは世界をリセットするためです。
オリジナルのコードに手を入れずに手っ取り早く世界をリセットする方法が他に思いつきませんでした...</p>
<h2>グラフの描画</h2>
<p>Rでグラフを描画します。</p>
<p>plot-evolution.R
<?prettify?></p>
<pre class="prettyprint">
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()
</pre>
<p>このRスクリプトを実行します。</p>
<p><?prettify?></p>
<pre class="prettyprint">
$ mkdir Rplot
$ Rscript --vanilla plot-evolution.R
</pre>
<p><code>Rplot/</code> 以下に連番のpngファイルが生成されます。</p>
<h2>結果</h2>
<p>まずは動物の個体数の遷移です。</p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1jF-GfFhO_-lInLesI4JuVHUT8StgfNUHQBZryIxG6_s9WK-OqIuA6hvfnVdKPpo8NdIJH4RDIhwuvkvpTvvpnjVeZvgaLURog5l5-es16Qh_ZjuB8FBfCaN78o8mK6Z2x0ZN3rToxMUe/s400/001.png" /></p>
<p>個体数は160前後で安定しています。これは植物が生える速度が常に一定のため、世界が平衡状態を保っているということでしょうか。</p>
<p>次に動物の直進率と個体数のヒストグラムを見てみます。</p>
<p>1万日後。まだ同じ傾向の動物しかいません。</p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMh7Omdw8tsXQbfgQ4Nd5ltFvHlssdNPw5L2sIEH2Sfi57RRTip7EtynES9CwGAeH6BG-L03moJUpKA7ULzlWz9nZcZZZJ5xjlOjRjYJHvfo7ITHlTm3QTLLAOsnCZa6WcRwJVK2bBWSkm/s400/002.png" /></p>
<p>3万日後。目立った変化無し。</p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm-dCcSS58KsBBAgEpM7FZcXfH60z2Y63se65VJ8oNxVBqSmhk1duIeaGVuS56KOofoa54-olUzmwyqI04BOg-27t50WVz-Li-czC3N0JBffY9lVHENRQvfKg2ZZtXg-XNbjoXFZEYREXh/s400/004.png" /></p>
<p>4万日後。種の分化が始まった!</p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmrdarpD9QPafphEsM9XxvQo8oaIqcqcy_I7FsoJam9vC2aRZrmNgoZVBAnsMrMho7bKwDYjudwbcpl8LYfQ_fsq43xisTPn0TA3onxIFreFR8AYM0_I5Q7Ll_yCOHlajJYIit_K1FblcA/s400/005.png" /></p>
<p>5万日後。完全に分かれました。</p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3hPY4nvfRsrG4qgKiqhallkgDU1A-VlhrxBPiW6RJO_VyQCuEUUKeTU-Sozg8Slc3LvIz0f1h3dnfKhgznYVZMN7tNJ4pHNC31LeM3iUUg4spPFRgsjvqcVFoO-cHzlLkl2PSYI0B0jp2/s400/006.png" />
<br></p>
<p>14万日後。ロバの直進率がさらに上がっています。</p>
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiclDOZtYcHGKFmXDJ5y8CV-ebPr81B8nGQYgGPUXydvUzCyuFFSOzwW2a5M4Ly02b_2pvKkhnC8Ae265A2CZxFKhziqDiqEbP5PefkGE_TkrQrO8K6G0eFzF04diwEX6fKsX3W2DtLz-Ic/s400/015.png" />
<br></p>
<h2>おわりに</h2>
<ul>
<li>種の分化の様子を見ることができて楽しかったです。</li>
<li>Common LispとRの連携はやっつけだったので他の手法も試してみたいです。</li>
<li>本の写経以外でCommon Lispのコードを書いたのは初めてなので、おかしなところがあったらどんどん指摘してください。</li>
</ul>
<h2>(追記)</h2>
<p>他の手法を試してみました: <a href="http://igjit.blogspot.jp/2013/07/evolution-rcl.html">Common LispでR (RCLを使ってみる)</a></p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-75819111480048127832013-06-05T22:51:00.000+09:002013-06-05T22:51:31.087+09:00Land of Lisp<p>Common Lisp始めました。</p>
<p>いま<a href="http://www.oreilly.co.jp/books/9784873115870/">Land of Lisp</a>を読んでいます。 <br />
Common Lispでゲームを作って遊べる!楽しい!</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2xur11YULFt60O0c2ZtW31SD_vIqFPLTmzJ2BoYHcTZvSOjwCvdn2uqMO_NF17ViA81Ekixs0UHh79upRFdzuKwkZUjt0uEVUVGcRc7Aurq1RWvloeK_rM6TYtk_UG3JVSIzpLXHy2A54/s1600/landoflisp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2xur11YULFt60O0c2ZtW31SD_vIqFPLTmzJ2BoYHcTZvSOjwCvdn2uqMO_NF17ViA81Ekixs0UHh79upRFdzuKwkZUjt0uEVUVGcRc7Aurq1RWvloeK_rM6TYtk_UG3JVSIzpLXHy2A54/s1600/landoflisp.jpg" height="240" width="320" /></a></p>
<p>読み終わったらまた感想書きます。</p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-54678564741855619602013-05-17T21:46:00.001+09:002013-11-11T21:48:59.587+09:00((Rで) 書く (Lisp) インタプリタ)<p>Rに慣れるために、Lispインタプリタを書いてみました。</p>
<p>元ねたはPeter Norvigの <a href="http://norvig.com/lispy.html">(How to Write a (Lisp) Interpreter (in Python))</a>
(日本語訳: <a href="http://www.aoky.net/articles/peter_norvig/lispy.htm">((Pythonで) 書く (Lisp) インタプリタ)</a>)です。</p>
<h2>コード</h2>
<script src="https://gist.github.com/igjit/5598108.js"></script>
<h2>遊び方</h2>
<p>コードを取ってきます。</p>
<p><?prettify?></p>
<pre class="prettyprint">
$ git clone https://gist.github.com/5598108.git
</pre>
<p>Rインタプリタを起動してコードを読み込ませます。 <br />
<code>repl()</code> を実行するとLispの対話式インタプリタが起動します。</p>
<p><?prettify?></p>
<pre class="prettyprint">
$ cd 5598108/
$ R -q
> source("lisp.R")
> repl()
lisp.R> (+ 1 2)
3
lisp.R> (define l (list 1 2 3))
(1 2 3)
lisp.R> (car l)
1
lisp.R> (cdr l)
(2 3)
lisp.R> (define add2 (lambda (x) (+ x 2)))
#<closure>
lisp.R> (add2 40)
42
lisp.R> (equal? (list 1 2) (list 1 (- 5 3)))
TRUE
lisp.R> (define map (lambda (f l) (if (null? l) (quote ()) (cons (f (car l)) (map f (cdr l))))))
#<closure>
lisp.R> (map add2 (list 10 20 30))
(12 22 32)
lisp.R>
</pre>
<h2>感想</h2>
<p>Rの言語機能(ファーストクラスの関数、レキシカルスコープ、クロージャなど)のおかげで、割と楽に書けたと思います。</p>
<p>ただリストの操作はちょっと面倒くさいかな、と思いました。 <br />
あと値渡しとか遅延評価とかでところどころはまりました。まだまだ慣れが必要です。</p>
<p>でも今回初めて使った機能がいくつかあって勉強になったし、何より言語処理系を作るのはとても楽しいです。</p>
<h2>(追記)</h2>
<p>続編を書きました。<a href="http://igjit.blogspot.com/2013/11/lispr-r.html">((Rで) 書く ((もっとRっぽい) Lisp) インタプリタ)</a></p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-34957831472478797762013-05-10T19:34:00.001+09:002013-05-10T19:34:56.879+09:00Rとクロージャ その2<p><a href="http://igjit.blogspot.jp/2013/04/r-closure.html">前回</a>の続きです。</p>
<p>Rのプロンプトで <code>demo(scoping)</code> を実行すると、クロージャの使用例を見ることができます。 <br />
<a href="http://mitpress.mit.edu/sicp/">SICP</a>の銀行口座 (<a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_sec_3.1.1">3.1.1 Local State Variables</a>)
をRで実装したものだと思います。</p>
<p><?prettify?></p>
<pre class="prettyprint">
> demo(scoping)
demo(scoping)
---- ~~~~~~~
Type <Return> to start :
> ## Here is a little example which shows a fundamental difference between
> ## R and S. It is a little example from Abelson and Sussman which models
> ## the way in which bank accounts work. It shows how R functions can
> ## encapsulate state information.
> ##
> ## When invoked, "open.account" defines and returns three functions
> ## in a list. Because the variable "total" exists in the environment
> ## where these functions are defined they have access to its value.
> ## This is even true when "open.account" has returned. The only way
> ## to access the value of "total" is through the accessor functions
> ## withdraw, deposit and balance. Separate accounts maintain their
> ## own balances.
> ##
> ## This is a very nifty way of creating "closures" and a little thought
> ## will show you that there are many ways of using this in statistics.
>
> open.account <- function(total) {
+
+ list(
+ deposit = function(amount) {
+ if(amount <= 0)
+ stop("Deposits must be positive!\n")
+ total <<- total + amount
+ cat(amount,"deposited. Your balance is", total, "\n\n")
+ },
+ withdraw = function(amount) {
+ if(amount > total)
+ stop("You don't have that much money!\n")
+ total <<- total - amount
+ cat(amount,"withdrawn. Your balance is", total, "\n\n")
+ },
+ balance = function() {
+ cat("Your balance is", total, "\n\n")
+ }
+ )
+ }
> ross <- open.account(100)
> robert <- open.account(200)
> ross$withdraw(30)
30 withdrawn. Your balance is 70
> ross$balance()
Your balance is 70
> robert$balance()
Your balance is 200
> ross$deposit(50)
50 deposited. Your balance is 120
> ross$balance()
Your balance is 120
> try(ross$withdraw(500)) # no way..
Error in ross$withdraw(500) : You don't have that much money!
>
</pre>
<p>銀行口座の状態(<code>total</code>: 残高)はカプセル化されていて、外部からは直接参照できません。
代わりにアクセサ(<code>deposit</code>: 預入れ、 <code>withdraw</code>: 払出し、 <code>balance</code>: 残高確認)
を通してやり取りしています。</p>
<p>オブジェクト指向っぽいものを簡単に実現できていて素敵ですね。</p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-89211237141325436292013-04-29T20:48:00.001+09:002013-04-29T20:48:50.026+09:00Rとクロージャ
<p>Rでクロージャを使ってみます。</p>
<h2>例:アキュムレータを生成する関数</h2>
<p>試しにPaul Grahamのエッセイ、<a href="http://practical-scheme.net/trans/icad-j.html">Revenge of the Nerds</a> に出てくる「アキュムレータを生成する関数」を書いてみます。</p>
<p>Schemeならこんな感じ。
<?prettify?></p>
<pre class="prettyprint">
gosh> (define (make-accumulator n)
(lambda (i)
(set! n (+ n i))
n))
make-accumulator
gosh> (define A (make-accumulator 5))
A
gosh> (A 10)
15
gosh> (A 10)
25
</pre>
<p>Perl5だと</p>
<p><?prettify?></p>
<pre class="prettyprint">
$ perl -de0
Loading DB routines from perl5db.pl version 1.33
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(-e:1): 0
DB<1> sub make_accumulator { \
cont: my $n = shift; \
cont: sub { $n += shift } \
cont: }
DB<2> $a = make_accumulator 5
DB<3> p $a->(10)
15
DB<4> p $a->(10)
25
</pre>
<p>(他の言語での実装は<a href="http://www.paulgraham.com/accgen.html">こちら</a>を参照。)</p>
<p>これをRで書くと</p>
<p><?prettify?></p>
<pre class="prettyprint">
> makeAccumulator <- function(n) {
+ function(i) {
+ n <<- n + i
+ n
+ }
+ }
> a <- makeAccumulator(5)
> a(10)
[1] 15
> a(10)
[1] 25
</pre>
<p>短く書くとこんな感じでしょうか。</p>
<p><?prettify?></p>
<pre class="prettyprint">
makeAccumulator <- function(n) function(i) (n <<- n + i)
</pre>
<h2>スーパーアサインメント演算子 <code><<-</code></h2>
<p>ポイントはスーパーアサインメント演算子 <code><<-</code> です。</p>
<p>通常の代入演算子 <code><-</code> は同じ環境の変数に代入します。</p>
<p><code><<-</code> は入れ子になった環境を順に外側に検索し、最初に変数の定義が見つかった環境に代入します。 <br />
見つからなかった場合はグローバル環境に代入します。 <br />
詳細は <code>help(<<-)</code> を実行してみてください。</p>
<p>今回の例では、内側の関数から、外側の関数の環境の <code>n</code> に代入したいので、 <code><-</code> ではなく <code><<-</code> を使う必要があります。</p>
igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0tag:blogger.com,1999:blog-3097595764143408742.post-46631766253877414942013-04-14T18:01:00.000+09:002013-04-14T18:04:40.469+09:00Ubuntu 12.04にRをインストールUbuntu 12.04に<a href="http://www.r-project.org/">R</a>をインストールします。<br />
<pre class="prettyprint lang-sh">$ sudo apt-get install r-base-core</pre>
<br />
Emacsから使いたい場合は<a href="http://ess.r-project.org/">ESS</a>も入れると良いです。
<br />
<pre class="prettyprint lang-sh">$ sudo apt-get install ess</pre>
Emacsを起動して M-x R で対話型インタプリタが立ち上がります。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHodYHZwMQZ42KNDb06BCR1uccWP528QSjRyFti58-mC7GxwivUdYMwfz0Mi7LYm1Szurcb41oSXyeJ2JYqPMz4qFVk4X4Obyt-BFPsYsMFhRrj7xqfLhN5E0YvVVHN4KWsg4j6Axf2SHx/s1600/SFFK0O~E.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHodYHZwMQZ42KNDb06BCR1uccWP528QSjRyFti58-mC7GxwivUdYMwfz0Mi7LYm1Szurcb41oSXyeJ2JYqPMz4qFVk4X4Obyt-BFPsYsMFhRrj7xqfLhN5E0YvVVHN4KWsg4j6Axf2SHx/s1600/SFFK0O~E.PNG" height="240" width="320" /></a></div>
<br />igjithttp://www.blogger.com/profile/00255089185676033183noreply@blogger.com0