Ntmuxは, 端末上のプログラムを TCP ソケットで制御できるプログラムであるが, この ntmux を用いると, 複数のプログラミング言語を同時に取り扱うことがとても簡単になる.
デモとして, プロジェクト・オイラー 問題 6
に対していくつかのプログラミング言語の解法を解説する文書を, それぞれインタープリタで動作確認しながら vim で執筆するという (ちょっとわざとらしい) デモ動画を撮ってみた.10以下の自然数について, 二乗の和と和の二乗の差は
(1 + 2 + ... 10)2 - (12 + 22 + ... + 102)
= 552 - 385
= 3025 - 385
= 2640
である.
100 以下の自然数について, 二乗の和と和の二乗の差を求めよ.
プログラミング言語の選択が異なる以外, 二つの動画はほとんど同じ内容.
以下のデモで, 各言語のインタープリタは HomeBrew などでインストールした後, 一切設定を行っておらず, vim 側でも言語毎の設定は一切行っていない.
Clojure だけは常用度が高いため, パッケージインストール直後という状態が良くわからなかったが, clojure-1.5.1.jar に CLASSPATH を通しただけの状態にしてある.
Clojure, Haskell and JavaScript 版のデモ動画
OCaml, Common Lisp and Python 版のデモ動画
Ntmux
Ntmux 自体については キッチンシンクの外へ出ようもご覧いただきたい.
Vim Script
デモ中の Vim Script を掲載しておく:
function! Send(host, port, msg)
python <<EOF
import vim
import socket
cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cs.connect((vim.eval('a:host'), int(vim.eval('a:port'))))
cs.sendall(vim.eval('a:msg'))
cs.close()
EOF
endfunction
function! GetSelected()
let tmp = @@
silent normal gvy
let selected = @@
let @@ = tmp
return selected
endfunction
command! -nargs=1 PSend call Send('localhost', <args>, GetSelected())
vnoremap cp <Esc>:PSend port<CR>
ヴィジュアルモードで範囲選択して cp とタイプすると, 変数 port に指定しておいたポートに TCP 接続し, 選択範囲の文字列を送信する.
Python 拡張が入っていないと動かない.
拙い例であるが, ご容赦いただきたい.
コード
デモの文書中に登場するコードも掲載しておく
Clojure
(- (#(* %%)(apply + (range 1101)))(apply + (map #(* %%)(range 1101))))
Haskell
((\x->x*x)$foldl1(+)[1..100])-(foldl1(+)$map(\x->x*x)[1..100])
JavaScript
functionrange(s,n){varr=[],i;for(i=s;i<n;i++)r.push(i);returnr;}((function(x){returnx*x;})(range(1,101).reduce(function(a,b){returna+b;}))-range(1,101).map(function(x){returnx*x;}).reduce(function(a,b){returna+b;}))
OCaml
letrangese=letrecfrse=ifs=ethenrelsef(s::r)(s+1)einList.rev@@f[]se;;letfoldl1fxs=matchxswithx::xs->List.fold_left(+)xxs;;((funx->x*x)@@foldl1(+)@@range1101)-(foldl1(+)@@List.map(funx->x*x)@@range1101);;
Common Lisp
(defunrange(se)(loopforifromsto(1-e)collecti))(-(funcall(lambda(x)(*xx))(apply#'+(range1101)))(apply#'+(mapcar#'(lambda(x)(*xx))(range1101))))
Python
((lambdax:x*x)(reduce(lambdaa,b:a+b,range(1,101)))-reduce(lambdaa,b:a+b,map(lambdax:x*x,range(1,101))))
それぞれは小規模過ぎて現実味が無いが, 「複数言語のそれぞれについて, 特有の環境を整備しなくてもここまでできる」という例としては十分と思う.
Conclusion
複数のプログラミング言語での開発において,
- 端末で動作する各言語のインタプリタがあれば, 同一のエディタや IDE のインスタンス内部で動作していなくても,
- それぞれの言語のインタプリタサーバを使わず ntmux のみを用い,
- 開発環境上に, それぞれの言語のプラグインではなく, 一つのプラグインのみを導入して
インタラクティブな開発が行える. そう Ntmux ならね.
課題
- ntmux
- ntmux から TCP クライアントへのレスポンスのルール決めと実装
- IPv6 対応
- MacOS X 以外のプラットフォームへの対応や動作確認
- vim プラグイン
- emacs プラグイン
など.
求むご意見・ご協力.