Emacs上のマルチな実行環境、Org-babel

NO IMAGE

いきなりですが、 Org-modeをご存知でしょうか。
Org-modeはEmacsで動作する高機能のアウトラインツール。何それ、Org-modeな方は r_takaishiさんの資料を一読される事をおすすめします。
org-mode を使おう

もっと知りたいという方は、以下のサイトを読んでOrg沼にはまってみるのもいいかもしれません。
OrgMode – Emacs上のアウトライナー

Org-modeはとにかく機能が豊富で、マニュアルも 200ページ近い大著です。実際、僕もごく一部の機能しか使いこなせていません。
にも関わらず、そのOrg-modeのフレームワークを利用した、これまた便利なツールを発見してしまいました。

Org-babel

Org-babelは、Org-modeを拡張するツールで、あらゆるプログラミング言語をorg-mode内で実行可能にします。圧巻なのは対応している言語の数で、なんと22の言語に対応しています。
Org-babel: Reference
聞いたこともないような言語もちらほらと。
ちなみに、名前にもなっているbabelですが、自然言語がバラバラになったきっかけの伝承として有名なバベルの塔のことを指しています。あらゆる言語をOrg-modeで実行可能にする、といった意味が込められているみたいです。
さらにちなみに、babelと名の付くプロジェクトって結構ありますね。GPSBabelもその一つですけど、やはりオレオレ仕様の固まりであるGPSのデータフォーマットを相互変換させるというとても素晴らしいプロジェクトで個人的にもかなりお世話になっています。つか、そろそろGoogleかGarminあたりが共通仕様提案すべきだと思うんですけどね。あ、ESRIはそんなことしたら駄目ですからね。糞フォーマットしか出さないから。
GPSBabel: convert, upload, download data from GPS and Map programs

設定

まずはOrg-modeがないと始まりません。Emacs23だとデフォルトで入っているのですが、バージョンが古いです。せっかくなので最新版使いましょう。
Org-Mode: Your Life in Plain Text
そしたら、Org-modeのファイル群にあるcontrib/lispディレクトリにload-pathを通しておいて.emacs辺りに(require ‘org-babel-init)と書いておけば良いです。
デフォルトで、使える言語はR,emacs-lisp,sh,perlpython,rubyなので、その他の言語を使いたい時は(require ‘org-babel-hogehoge)などとしておけば良いようです。

org-babelでは、ブロックを頻用します。yasnippetをすでに使っている方は使ってみると効率があがるかもしれないですね。
まずは、githubからorg-mode用のsnippetを取ってきます。
RickMoynihan’s yasnippet-org-mode at master – GitHub

yasnippetが新しめのバージョンであれば(0.6.0以上?)、以下のコードを.emacsあたりに書いておきます。
[cpp]
(defun yas/org-very-safe-expand ()
(let ((yas/fallback-behavior ‘return-nil)) (yas/expand)))

(add-hook ‘org-mode-hook
(lambda ()
;;yasnippet (using the new org-cycle hooks)
(setq ac-use-overriding-local-map t)
(make-variable-frame-local ‘yas/trigger-key)
(setq yas/trigger-key [tab])
(add-to-list ‘org-tab-first-hook ‘yas/org-very-safe-expand)
(define-key yas/keymap [tab] ‘yas/next-field)))

[/cpp]

1分で始めるOrg-babel

使い方はとても簡単。#+BEGIN_SRCで始まり#+END_SRCで終るブロック内に何がしかのコードを書いていきます。emacs-lispだと例えばこんな感じ。

[cpp]
#+BEGIN_SRC emacs-lisp
"hoge"
#+END_SRC
[/cpp]

ブロック内でC-c ‘ とすると編集用のバッファが各言語のモードで開きます。使いなれたモードでコーディングできるのですこぶる便利。
ひとしきり書きおわったなら、同じくブロック内でC-c C-cすると実行結果が返ってきます。こんだけです。

言語間で連携

これだけだとあんまりなので、応用編。各言語の実行結果はいったんorg-modeのテーブルなどに置きかえられることによって、共有することが可能です。というわけで、簡単な例を何個か。シェルスクリプトとelispの実行結果をRに渡しています。orgファイルからコピペしただけなのでちょっとわかりづらいかも。。。
[cpp]
* 複数言語連携の例
** ホームディレクトリの容量割合を円グラフにする。
シェルスクリプトの結果をRで描画

#+srcname: sh2R
#+BEGIN_SRC sh
cd ~ && du -sc * |grep -v total
#+END_SRC

#+results: sh2R
| 1284 | Desktop |
| 1147760 | Documents |
| 649640 | Downloads |
| 8 | Mail |
| 4 | Music |
| 4 | Pictures |
| 4 | Public |
| 4 | Templates |
| 4 | Videos |
| 4 | examples.desktop |
| 15032 | workspace |
| 1813748 | 合計 |

#+BEGIN_SRC R :session ex :file dirs.png :var dirs=sh2R
pie(dirs[,1], labels = dirs[,2])
#+END_SRC
出力結果
#+results: pie-chart
[[file:dirs.png]]

** 行列のたし算
emacs lispのリストをRに渡す。
#+srcname: elisp2R
#+BEGIN_SRC emacs-lisp
‘((1 2 3)
(4 5 6)
(7 8 9))
#+END_SRC

受けとったリストを使って計算
#+BEGIN_SRC R :session ex :var e2r=elisp2R
e2r + e2r
#+END_SRC

出力結果
#+results:
| 2 | 4 | 6 |
| 8 | 10 | 12 |
| 14 | 16 | 18 |

[/cpp]

さくっと公開してみる

org-modeの良いところとして、HTMLやpdfなどいろいろな媒体でさくっと公開できるというのもあると思います。当然Org-babelもその機能を存分に生かせるようになってます。次のorgファイルは、先ほどの例に何個加筆したものですが。。。
[cpp]
#+TITLE: Org-babelの使い方
#+AUTHOR: myuhe

* Rで使ってみる
簡単な計算をしてみる。
#+BEGIN_SRC R
x <- 1:10
mean(sqrt(x))
#+END_SRC

ブロック内でC-c C-cすると実行される。
#+results:
: 2.24682781862041

グラフの出力も可能。埋めこんだ形で出力される。
#+BEGIN_SRC R :file density.png
plot(density(rnorm(100)))
#+END_SRC
出力結果
#+results:
[[file:density.png]]

* Pythonの例
単純な計算
#+begin_src python
a = 1
b = 2
return a + b
#+end_src
pythonの場合、出力には明示的にreturnしてあげる必要がある。
#+results:#+results:
: 3

* 複数言語連携の例
** ホームディレクトリの容量割合を円グラフにする。
シェルスクリプトの結果をRで描画

#+srcname: sh2R
#+BEGIN_SRC sh
cd ~ && du -sc * |grep -v total
#+END_SRC

#+results: sh2R
| 1284 | Desktop |
| 1147760 | Documents |
| 649640 | Downloads |
| 8 | Mail |
| 4 | Music |
| 4 | Pictures |
| 4 | Public |
| 4 | Templates |
| 4 | Videos |
| 4 | examples.desktop |
| 15032 | workspace |
| 1813748 | 合計 |

#+BEGIN_SRC R :session ex :file dirs.png :var dirs=sh2R
pie(dirs[,1], labels = dirs[,2])
#+END_SRC
出力結果
#+results: pie-chart
[[file:dirs.png]]

** 行列のたし算
emacs lispのリストをRに渡す。
#+srcname: elisp2R
#+BEGIN_SRC emacs-lisp
‘((1 2 3)
(4 5 6)
(7 8 9))
#+END_SRC

受けとったリストを使って計算
#+BEGIN_SRC R :session ex :var e2r=elisp2R
e2r + e2r
#+END_SRC

出力結果
#+results:
| 2 | 4 | 6 |
| 8 | 10 | 12 |
| 14 | 16 | 18 |

[/cpp]
これをhtmlに変換すると以下のようになります。ちなみに変換はorg-export-as-htmlを実行しただけ。楽ちん。

Org-babelの使い方

Org-babelはマルチな実行環境

Org-babelはorg-modeを常用する人にとっては、Org-modeがお手軽な実行環境にもなるわけですので、導入しといて損はないと思います。後、メリットがありそうな人といえば。。。
・Rでレポートを書いている学生さん
Org-babelでは、かなりR関連の機能が充実しています。これを使えば、出力したグラフなどを切り貼りすることなく、ひたすら org-modeを編集していくだけで素晴らしいレポートができるんではないかな、と思います。
・オレオレWikiとかでコーディングメモを取っている人。
本業がアウトラインツールであるOrg-modeなので、整理しながら編集していくことがとても得意です。 Org-babelではその上に実行環境まで付いてくるので、ちょこちょこコード書いては実行してまとめていくなんてこともできます。個人的にはこういった使い方をしていこうかな、と思っています。

Org-babelはまだ できたばかりでもあって、実は結構バギーだったりしますが、それでもこのお手軽感は魅力。 org-mode使ってない、という方もこれを機に試してみるといいかもですね。

参考

Org-babel: Introduction
Org-babel: Reference
Emacs org-modeを使ってみる: (40) org-babel-Rを使う1/2 – 屯遁のパズルとプログラミングの日記
Emacs org-modeを使ってみる: (41) org-babel-Rを使う2/2 – 屯遁のパズルとプログラミングの日記

[tmkm-amazon]1906966087[/tmkm-amazon]

[tmkm-amazon]4774143278[/tmkm-amazon]