ecl (2)

日経Linuxあたりで、ラズパイとかを使って、温度監視システムを作りましょなんて、 電子工作を勧めている。多角経営に乗り出さないと、里奈だけじゃ食っていけないからだな。 毎度、Winを目の仇にして、里奈への勧誘だけじゃ、飽きられちゃうからね。

でも、電子工作の基本は、Lチカからだと思うんよ。このLEDチカチカは、Hardware界の Hello world だもの。

Lチカするなら、2石でマルチバイブレータを組むのが定石でしょう。それよか少し高級に なるとPICでしょう。

ARMの石もいいけど、pic funなんていう遊園地も楽しそうだぞ。 定番のPICを使った、 PIC12Fシリーズの製作例集なんてのもある。

アセンブラで頭の体操をするも良し、CCS-Cを使ってコンパイルしても良し。 ハードもソフトもメカも組み合わせれば、総合レジャーランドになるぞ。

あれが動くかな

前々回だかにやった、方程式を解くやつ。作者さんはCLISPでやっておられたけど、果たして eclでも動くのだろうか? 早速、互換性テスト実施

> (load "bidirection.lisp")

;;; Loading "/home/sakae/src/cl/bidirection.lisp"

Condition of type: STREAM-DECODING-ERROR
decoding error on stream #<input stream #P"/home/sakae/src/cl/bidirection.lisp"> (:EXTERNAL-FORMAT ...
Available restarts:

1. (CONTINUE) Read next character
2. (USE-VALUE) Replace the bogus sequence with a character
3. (RESTART-TOPLEVEL) Go back to Top-Level REPL.

いきなりのエラーだよ。CLの場合、何かあると盛大にえらーだぞ、どうする? って聞いて 来るんで、この流儀に慣れないと、気持ちが萎えてしまうぞ。

でも、ちゃんと原因を報告してきてるから、まずは気持ちを落ち着けるんだ。デコードエラー って言ってきてるな。ソースファイルの文字コードが不味いんだろうな。確認してみる。

sakae@uB:~/src/cl$ nkf -g bidirection.lisp
Shift_JIS
sakae@uB:~/src/cl$ nkf -w bidirection.lisp > a.lisp

文字コードが、島国根性丸出しになってたんで、国際コードに変換したよ。され、これで 動くかな?

> (load "a.lisp")

;;; Loading "/home/sakae/src/cl/a.lisp"
#P"/home/sakae/src/cl/a.lisp"
> (fc -h)

(- (* 5.0 (- F 32.0)) (* 9.0 C))
> (fc c 20)

68.0

そして、気温20度C を、アメリカ版、気温に変換してみたぞ。全く、アメリカって困った国 だのう。誰か、長さ、重さ、容量の変換コードを書かないかな。

eclの内部観察

ソースを自前でコンパイルして動かしている手前、内部がどう動いているか、観察したく なりませんか? そういう時は、gdbが使えるように

make ECL_DEBUG=1

しておきます。いきなりeclに当たろうとしても無理なんで、build/ecl_min に当たるのが吉。 build 配下には、.gdbinitとかTAGSまで用意されてますから。(TAGSって事は、emacsを準強要 されるって事です)

;*** Lisp core booted ****
ECL (Embeddable Common Lisp)

ecl_minを起動してプロンプトが出てきた所で、Ctrl-Cした時、gdbが立ち上がり、そこで btしてみた。

#0  0xb7fdd424 in __kernel_vsyscall ()
#1  0xb7eece1b in read () at ../sysdeps/unix/syscall-template.S:81
#2  0x0806714d in read (__nbytes=1, __buf=0xbffff487, __fd=0) at /usr/include/i386-linux-gnu/bits/unistd.h:44
#3  io_file_read_byte8 (strm=0x84d7e70, c=0xbffff487 "\267", n=1) at /home/sakae/ecl-13.5.1/src/c/file.d:2652
  :
#11 0x0807062e in cl_read (narg=narg@entry=3) at /home/sakae/ecl-13.5.1/src/c/read.d:1518
#12 0x0804c3a4 in si_simple_toplevel () at /home/sakae/ecl-13.5.1/src/c/cinit.d:170
#13 0x0807fc15 in dispatch0 (narg=0) at /home/sakae/ecl-13.5.1/src/c/cfun_dispatch.d:10
#14 0x0804c18e in main (argc=1, args=0xbffff704) at /home/sakae/ecl-13.5.1/src/c/cinit.d:203

もう一つやってみる。carした時breakさせてみる。ソース上では、c/cons.d/の中にある、ecl_carが 相当するようだ。

(gdb) bt
#0  ecl_car (x=x@entry=0x81d6c39) at /home/sakae/ecl-13.5.1/src/c/cons.d:371
#1  0x08053ad7 in cl_car (x=x@entry=0x81d6c39) at /home/sakae/ecl-13.5.1/src/c/cons.d:818
#2  0x080a39fc in si_pathname_translations (narg=narg@entry=2, host=0x84d2fd8, host@entry=0x81621fc <str_sys_data>) at /home/sakae/ecl-13.5.1/src/c/pathname.d:1566
#3  0x0804de1a in cl_boot (argc=argc@entry=1, argv=argv@entry=0xbffff704) at /home/sakae/ecl-13.5.1/src/c/main.d:676
#4  0x0804c0b9 in main (argc=1, args=0xbffff704) at /home/sakae/ecl-13.5.1/src/c/cinit.d:185

なお、ecl_car とは別に、c_car なんてのもあるようだ。(TAGSをgrepしたら出てきた) このc_carは、ecl_minのプロンプトから呼び出した時に使われるようで、compiler.dの中に 定義されてる。btの結果は

(gdb) bt
#0  c_car (env=0xb7fda000, args=0x81d6581, flags=2) at /home/sakae/ecl-13.5.1/src/c/compiler.d:2549
#1  0x0805ca22 in compile_form (env=env@entry=0xb7fda000, stmt=stmt@entry=0x81d65e1, flags=flags@entry=2) at /home/sakae/ecl-13.5.1/src/c/compiler.d:2292
#2  0x0805d25d in compile_with_load_time_forms (env=env@entry=0xb7fda000, form=form@entry=0x81d65e1, flags=flags@entry=2) at /home/sakae/ecl-13.5.1/src/c/compiler.d:2445
#3  0x0805d525 in eval_nontrivial_form (form=0x81d65e1, env=0xb7fda000) at /home/sakae/ecl-13.5.1/src/c/compiler.d:2370
#4  eval_form (env=env@entry=0xb7fda000, form=form@entry=0x81d65e1) at /home/sakae/ecl-13.5.1/src/c/compiler.d:2388
#5  0x0805fd10 in si_eval_with_env (narg=narg@entry=1, form=0x81d65e1) at /home/sakae/ecl-13.5.1/src/c/compiler.d:3129
#6  0x0804c360 in si_simple_toplevel () at /home/sakae/ecl-13.5.1/src/c/cinit.d:173
#7  0x0807fc15 in dispatch0 (narg=0) at /home/sakae/ecl-13.5.1/src/c/cfun_dispatch.d:10
#8  0x0804c18e in main (argc=1, args=0xbffff704) at /home/sakae/ecl-13.5.1/src/c/cinit.d:203

対応するコード部分

  static int
  c_car(cl_env_ptr env, cl_object args, int flags)
B {
  n       cl_object list = pop(&args);
          if (args != ECL_NIL) {
                  FEprogram_error_noreturn("CAR: Too many arguments", 0);
          }
          compile_form(env, list, FLAG_REG0);
  =>      asm_op(env, OP_CAR);
          return FLAG_REG0;
  }

おお、matzさん得意の仮想マシンかな。上のトレースを眺めると、ソースの土地勘が出て くるな。次は、src/h/bytecodes.h あたりを見て、おくかな。で、開いてみたら、 src/c/interpreter.d も見ると吉って、お勧めされてた。ちょいと覗き見したら、スレテッドなんて 言葉が出てきたけど、 トークンスレッデッドコードマシン とかも関係するのかしらん。

profile

通過儀式って事で、profile出来ないか調べてみる。するとcontribに入っていたよ。

;;;; This software is part of the SBCL system. See the README file for
;;;; more information.
;;;;
;;;; This software is derived from the CMU CL system, which was
;;;; written at Carnegie Mellon University and released into the
;;;; public domain. The software is in the public domain and is
;;;; provided with absolutely no warranty. See the COPYING and CREDITS
;;;; files for more information.

(eval-when (:compile-toplevel :load-toplevel)
  (defpackage "PROFILE"
    (:nicknames "PROF" "SB-PROFILE")
    (:export "PROFILE" "REPORT" "RESET" "UNPROFILE" "UNPROFILE-ALL"))
)

(in-package "PROFILE")

profile.lispの冒頭部分。仰せに従って、鉄鋼銀行Lispの説明を見る。 どうも、この説明と、このファイルの実体は違うようだ。だって、外から見えるように してくれてる、exportされてる関数が微妙に違うから。 で、原典になったという、カーネギーメロン大学の方の Profiling を見る。どうもこちらのようだ。

使い方は、profileマクロを使って、観察したい関数を登録。後は、関数を適当に実行。 それからreportしてね。結果は累積されてくんで、クリアする場合、resetを発行するとな。 監視を止める場合は、unprofileって事だな。

> (package-name *package*)

"COMMON-LISP-USER"
> (use-package 'profile)

Condition of type: SIMPLE-PACKAGE-ERROR
There exists no package with name PROFILE

ポール本の210ページからパッケージの使い方がさらっと書いてある。噂によるとポールは、 余りパッケージシステムが好きでは無いようだ。だから、ちからが入らないんだな。彼が 好きなのはマクロ。マクロ専門本 On Lispなんてのを書いてるぐらいだから。 そんなものだろうね。今では、マクロがLispのアドバンテージだもの。

オイラー並みにパッケージを理解すると、パッケージってディレクトリーなんだな。 今居る場所は、Unixならpwdで確認するけど、CLだとpackage-nameコマンドで確認。

別Dirになってるのを参照するには、UnixだとPATHを通すって操作をするけど、CLだとuse-package なんだな。指定したDirへ行くには、Unixだとcdだけど、CLだと、in-packageになるんか。 mkdirの対応品は、あれれ? そういう時は、CLに聞いてみるのが手っ取り早い。

> :apropos package
*PACKAGE*  has value: #<"COMMON-LISP-USER" package>
  :
LIST-ALL-PACKAGES  Function
MAKE-PACKAGE  Function
USE-PACKAGE  Function
WITH-PACKAGE-ITERATOR  Macro

色々と出てきたな。どんなパッケージが有るかも確認出来るんか。

> (LIST-ALL-PACKAGES)

(#<"ECL-CDB" package> #<"FFI" package> #<"GRAY" package> #<"MP" package>
 #<"CLOS" package> #<"C" package> #<"SI" package> #<"EXT" package>
 #<"KEYWORD" package> #<"COMMON-LISP-USER" package> #<"COMMON-LISP" package>)

あれ? お目当てのprofileが無いぞ。これって、ひょっとして隠しパッケージなのかなと unix-userは思ってしまうのでした。

こういう時は、Lispの総合開発環境、emacs+slimeに任せてみるのも手かも知れません。 Slimeのキーバインド なんてのを参照してみました。そしたら、ちゃんと有るじゃないですか。profileメニューが。

実験材料を用意しました。

sakae@uB:~/src/cl$ cat z.lisp
(defun tak (x y z)
    (if (<= x y )
        z
        (tak (tak (- x 1) y z) (tak (- y 1) z x) (tak (- z 1) x y))))
(defun fact (n) (if (zerop n) 1 (* n (fact (- n 1)))))
(defun add1 (n) (1+ n))
(defun sq (n) (* n n))

tak,fact,add1,sqなんてのを定義。

CL-USER> (load "/home/sakae/src/cl/z.lisp")
#P"/home/sakae/src/cl/z.lisp"
CL-USER> (fact 10)
3628800
CL-USER> (tak 12 6 0)
measuring PROFILE overhead..done
  seconds  |   consed  |  calls |  sec/call  |  name
--------------------------------------------------------
     0.000 | 4,581,360 | 63,609 |   0.000000 | TAK
     0.000 |         0 |     11 |   0.000000 | FACT
--------------------------------------------------------
     0.000 | 4,581,360 | 63,620 |            | Total

estimated total profiling overhead: 0.14 seconds
overhead estimation parameters:
  4.e-8s/call, 2.256e-6s total profiling, 8.4e-7s internal profiling

These functions were not called:
 ADD1 SQ

実験材料を読み込んでおいてから、CL-USERってパッケージ内の全てをプロファイルしてねって指示。 それから、お目当てを実行。そして結果表示。 親切な事に、まだ試験してない関数も有るよって教えてくれています。

でも、ちょっと結果が変だぞ。実行時間が取れていない。使い方の間違いも無さそうだし、 どうしたものかな? そんなの聞くまでも無い、ソース嫁。

その前に、別の手法でプロファイルしてみる。cmuclのwebに紹介されてたやつ。

time

まずは、素直に使ってみる。

> (time (tak 18 9 0))

real time : 10.470 secs
run time  : 10.213 secs
gc count  : 102 times
consed    : 759824144 bytes
9

何回も回す場合は、loopの魔界を使うか

> (time (loop repeat 100 do (fact 1000)))

real time : 0.161 secs
run time  : 0.120 secs
gc count  : 7 times
consed    : 58299976 bytes
NIL

易しい繰り返しを使うのが、素直かつ脳内負荷の低減に役立ちます。

> (time (dotimes (i 100) (fact 1000)))

real time : 0.149 secs
run time  : 0.152 secs
gc count  : 5 times
consed    : 936758312 bytes

この時点で、profileのBUG確定ですな。timeマクロで、ちゃんと時間計測出来ているんですから! こういうトラブルが有ると、生きた勉強になりそう。 その前に

slimeでは?

ちゃんと、profileを見つけて動かしてくれた。これってどゆ事? 変な疑問、もとえまっとうな 疑問が湧いてきましたなあ。slimeのコードも嫁ってか。

まてまて、emacsの裏bufferに*slime-events*という監視カメラが有ってだなあ。それに オイラーとeclとのやり取りがみーんな記録されてるんよ。そいつを見れば、どんな要求を 突きつけたか一発だわい。

(:emacs-rex
 (swank:list-all-package-names t)
 "COMMON-LISP-USER" :repl-thread 12)
(:return
 (:ok
  ("SWANK-IO-PACKAGE" "SWANK" "SWANK-RPC" "SWANK-MATCH" "SERVE-EVENT" "PROFILE"\
 "SB-PROFILE" "PROF" "SB-BSD-SOCKETS" "SWANK-MOP" "SWANK-BACKEND" "SWANK-LOADER\
" "ASDF/FOOTER" "ASDF/USER" "ASDF-USER" "ASDF/INTERFACE" "ASDF" "ASDF-UTILITIES\
" "ASDF/SOURCE-REGISTRY" "ASDF/BACKWARD-INTERFACE" ...))
 12)
(:emacs-rex
 (swank:profile-package "CL-USER" t t)
 "COMMON-LISP-USER" :repl-thread 13)
(:return
 (:ok nil)
 13)
   :
(:emacs-rex
 (swank:profile-report)
 "COMMON-LISP-USER" :repl-thread 31)
(:write-string "measuring PROFILE overhead..done\n")
(:write-string "  seconds  |   consed  |  calls |  sec/call  |  name  \n-------\
  :

デカ長さん(刑事物の凝ってるんで使ってみたのさ)の分析によると、eclに向かって、オイラーの 代理人(slime)が、お前、どんなサービスしてくれるん?

で、いろいろと答えが返ってきました。そなら、profile-packageってのが有るはずだから、 そいつを頼むわ。

そんでもって、結果を返せとな。このやり取りを裏で支えているのにswankってやつが想像 出来るけど、ここでは尻尾を出していません。まあ、多分そんな事でっしゃろう。

念の為、裏取りって事で、slime/swank-ecl.lispの中を覗いてみたら

(defimplementation profile (fname)
  (when fname (eval `(profile:profile ,fname))))
   :

こんなのに出くわした。これって、slimeのコマンドを、ecl側のパッケージに結び付けて いるんだな。このファイルには、emacs側と通信する為のサーバーを立てる処理も書いて あったよ。で、これが翻訳された結果であるswank-ecl.fasがecl側で起動してた。 以下、その証拠を入手。slimeでeclを起動した後の状態

sakae@uB:~$ lsof -c ecl| awk  '{print $9}' | grep sakae | cut -f15 -d '/'

swank.fas
swank-rpc.fas
swank-match.fas
swank-gray.fas
swank-ecl.fas
swank-source-file-cache.fas
swank-backend.fas
swank-source-path-parser.fas

基本、lsof -c eclだけで良いんだけど、出力がごちゃごちゃしてたんで、パイプを通して 洗浄してます。

でもどうやって、emacsからeclを起動してんの? こっそりemacsを尾行してみるかな。

sakae@uB:~/t$ strace emacs &> LOGemacs
sakae@uB:~/t$ strace -f emacs &> LOGecl

上段は親側のemacsの挙動追跡。これだと煙に巻かれてしまって肝心な所が察知出来ない。 だって、emacsがeclって子共を生むんだけど、子の追跡はしてくれないのよ。

そんな訳で、生まれた子共もしっかり追跡出来るように、オプションを追加しました。 家にある唯一のsyscall解説書を、あわてて参照したよ。そしたら、子共を生む方法が 書いてあった。

親(emacs)が、vforkして、うり二つのプロセスを生成する。生まれた子供をexecveを使って eclに変身させる。親は子が死ぬのをじっと観察してて、死んだら、wait4で葬式を出してやる。 子供が死んでしまっても、親はまだまだ生き続ける(のが普通)。

たまたま親が先に死んだ後に子が死ぬと、葬式を出してもらえないので、子はゾンビになる。 みかねた神様のinit様が、ゾンビを成仏させてあげる。こういう世界なんだな。目の前で 動いているOSは。

sakae@deb:~/t$ grep execve LOGecl
execve("/usr/bin/emacs", ["emacs"], [/* 19 vars */]) = 0
[pid  2803] execve("/usr/local/bin/ecl", ["/usr/local/bin/ecl"], [/* 22 vars */] <unfinished ...>
[pid  2803] <... execve resumed> )      = 0

emacsが引数無しで起動され、そこからeclと言う子供が生まれたとな。子供の背番号は2803って 事が分かる。最後は子供を看取って、成仏した事を確認してるな。教科書通りの世界だ。

sakae@deb:~/t$ grep open LOGecl | grep slime
  :
open("/home/sakae/.emacs.d/slime/slime.el", O_RDONLY|O_LARGEFILE) = 4
open("/home/sakae/.emacs.d/slime/contrib/slime-repl.el", O_RDONLY|O_LARGEFILE) = 5
  :
[pid  2803] open("/home/sakae/.emacs.d/slime/swank-loader.lisp", O_RDONLY|O_LARGEFILE) = 6
[pid  2803] open("/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-backend.fas", O_RDONLY) = 6
   :

一方、こちらはslime関係の利用状況。slime.elとその関係者を親のemacsがまず利用。 子供の方は元気よく生まれたら、swan-loader.lispなんてのを呼び出すんだな。その力を 借りて、ecl側の環境を整え、親と交信出来るようにチャンネルを開くんか。

大まかには、上記の説明で良いだろうけど、おぎゃーと生まれたeclがどうやってswank-loader.lispを 嗅ぎ付けて、呼び出すの? そこが不思議。単独で起動したeclは、勿論swank-loader.lisp なんて呼び出さないし。。。

ニュートン誌で、新生児の誕生の仕組みが解説されてた。母体から分離(出産の事ね)した 時、心臓の大工事を行い血液の流れを変える事や、肺の自動起動の仕組みが解説されてて 、生命の不思議さに心を打たれましたよ。

ちなみに、肺の自動起動はどうなってるかと言うと。。。母体の中に居る時は新生児の肺は 肺水に満たされていて機能していない。必要な酸素はへその緒を通じて流れてくる血液から 得ているとか。産道を通って出てくると、肺が圧迫されて肺水が吐き出される。これを トリガーにして、産声と言う肺活動を開始するとな。肺が一時的にぺしゃんこになる訳 だけど、潰れた肺がペタンとくっつかないように、すぐに膨らむように、肺水には界面活性剤 相当の成分が含まれているらしい。何と手回しの良い事。こういう話を聞くと、神の意思を 感じぜずにはいられないな。

それに比べたら、生まれたeclが親と通信出来るようになるなんて、小さい事だろうけど、 どうやってるの? 何か見落としが有るのだろうな。

案として、起動時に引数で渡す、環境変数で渡す、特定なパイプを開いておく、eclがemacsの 起動してる事を自分で察知する、ぐらいかなあ。

親は子供の番号を知ってるけど、子供は親の番号を直接は知らない、まてよ、getppidなんてのが 有ったな。調べてみたけどgetppidなんて使われていなかった。

後はシグナルで通知かなあ。もう少し考えてみよう。

eclでサーバー構築

slimeの中のファイルをぼーっと眺めていたら、start-swank.lisp なんて興味を引くやつに気付いた。 早速開いて点検してみると、CL側でサーバーを立てる為の起動スクリプトである事が判明。 サーバーと言っても、slime語を喋るサーバーですけど。

slimeとかswankとか勝手に出てきてるんで、ちょっと整理しとく。

emacsとCLのやり取りが必要。CLは共通Lispって事だけど、やはり微妙に個性がある。 そこで、emacsと各種CL間のやり取りをするプロトコルを有志が定めた。このプロトコル がslime。各種CL側がサーバを建ててemacsからのslime語を待ちうけ、それに応答する。 各種CL側で動くサーバーやslime語の解釈は、swank-xxってので行う。xxの部分は、CLに 共通な部分と、個別CL用と分かれていて、詰め合わせセットで提供されてる。

sakae@deb:~/.emacs.d/slime$ ecl  -load start-swank.lisp
;;; Loading "/home/sakae/.emacs.d/slime/start-swank.lisp"
;;; Loading "/home/sakae/.emacs.d/slime/swank-loader.lisp"
;;; Loading #P"/usr/local/lib/ecl-13.5.1/cmp.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-backend.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-source-path-parser.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-source-file-cache.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-ecl.fas"
;;; Loading #P"/usr/local/lib/ecl-13.5.1/sockets.fas"
;;; Loading #P"/usr/local/lib/ecl-13.5.1/profile.fas"
;;; Loading #P"/usr/local/lib/ecl-13.5.1/serve-event.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-gray.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-match.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank-rpc.fas"
;;; Loading "/home/sakae/.slime/fasl/2013-06-26/ecl-13.5.1-linux-pentium3/swank.fas"
;;; Warning: These Swank interfaces are unimplemented:
 (ACTIVATE-STEPPING ADD-FD-HANDLER ADD-SIGIO-HANDLER BACKGROUND-SAVE-IMAGE DUP
  EXEC-IMAGE FRAME-CALL LIST-CALLEES LIST-CALLERS MACROEXPAND-ALL
  MAKE-FD-STREAM REMOVE-FD-HANDLERS REMOVE-SIGIO-HANDLERS RESTART-FRAME
  RETURN-FROM-FRAME SAVE-IMAGE SLDB-BREAK-AT-START SLDB-BREAK-ON-RETURN
  SLDB-STEP-INTO SLDB-STEP-NEXT SLDB-STEP-OUT TOGGLE-TRACE)
;; Swank started at port: 4005.

何やら、見慣れたファイルをローディングしてるなあ。最後に、port 4005で待ってるからね って言ってきた。これが、80番とか443だったら、一般受けするんだろうけど。。。

別端末からemacsを起動して、M-x slime-connect して、localhostの4005番に接続したら、 見慣れた、やつが

ECL  Port: 4005  Pid: 2401
------------------------------------------------------------------------
; SLIME 2013-06-26
CL-USER>

TCPを使って、emacsとeclが結ばれましたねぇ。なお、件のファイルには、

;;; For additional swank-side configurations see
;;; 6.2 section of the Slime user manual.

なんて、親切にポインターが紹介されてましたよ。これを読むと、通信の秘密が解けるのだるか? 騙されたと思って読んでみれ。刑事物語風に言うと、靴をすり減らして、地取りをせいって 事なんですなあ。そう言えば、昔有った、3億円強奪事件を執念で追ってた刑事が居たなあ。 本を探して、また読んでみるかな。

気になったんで、slime.elを眺めてみたんだ。

;;;
;;;   0. Emacs recompiles/reloads slime.elc if it exists and is stale.
;;;   1. Emacs starts an inferior Lisp process.
;;;   2. Emacs tells Lisp (via stdio) to load and start Swank.
;;;   3. Lisp recompiles the Swank if needed.
;;;   4. Lisp starts the Swank server and writes its TCP port to a temp file.
;;;   5. Emacs reads the temp file to get the port and then connects.
;;;   6. Emacs prints a message of warm encouragement for the hacking ahead.
;;;
;;; Between steps 2-5 Emacs polls for the creation of the temp file so
;;; that it can make the connection. This polling may continue for a
;;; fair while if Swank needs recompilation.

なんてこったい、灯台本暗しだな。親から子へ標準道路を経由して、サーバーの起動を 促しているんか。そして、サーバー起動後も秘密の通路は確保しとくとな。これって、 隠れた親子のキズナでしょうか。麗しや。

ああ、それにしてもslime.elの行数が長すぎるぞ、9500行近くあるぞ。まあ、このファイルは emacs側の画面制御やslime語の送受信と解釈まで、一括して行うブラウザーだから 大きくなるのも当然か。

でも、今回の要所は上記の部分だな。後はオンデマンドで大丈夫。最後に、実験。

sakae@deb:~/.emacs.d/slime$ echo ':ld start-swank.lisp' | ecl
   :
;; Swank started at port: 4005.

こういう事が出来るのね。知らんかったぞ。これを見て、遠い昔にWebサーバーでcgiを やったのを思い出したぞ。cgiもプロトコルだったな。Webサーバーとcgi側は、標準入出力を 介して繋がってたな。

ManKai Common Lisp (MKCL)

eclからフォークしたと言う ManKai Common Lisp (MKCL) なんてのをLisp netで見つけた。これって、CMU CLから分家したsbclみたいなものだな。 果たして、主流になるか、生暖かく見守りたいと思います。

所で、上記は正式に、ManKaiって書いてるけど、これって、満開から取ったんだろうか。 どうも外人は、漢字に憧れるようで、よく努力とかなんて漢字を刺青に彫っている人が居るな。

おいらのお勧めは闘魂Lispとか絆Lispだったりするけど、どうでしゃろ? あちらの方。 そう言えば、キズナなんて名前のお馬さんが居ますなあ。安田記念では果たして勝つでしょうか。

早速、ウブでやってみると

;;; Compiling /usr/share/common-lisp/source/cl-asdf/build/asdf.lisp.Error during command line arguments processing:
Error: in file /usr/share/common-lisp/source/cl-asdf/build/asdf.lisp, end position 208893,
   and form: (WITH-UPGRADABILITY NIL (MAP NIL 'REGISTER-IMAGE-RESTORE-HOOK ...))
raw-command-line-arguments not implemented yet.
  :
You are recommended to compile again..
make[1]: *** [trivial-features.fasb] Error 1
make[1]: Leaving directory `/home/sakae/mkcl-1.1.8/src'
make: *** [all] Error 2

あえなく撃沈。作者の方は、12.04 LTSでやってるって事なんで、cl-asdf(rubyで言ったら、gem みたいなもの、ああ、そこまでデフォになってないかasdfは)は、古めなんでしょうかね。

しょうがないので、fedoraでやったら動いた。

[sakae@fedora ~]$ mkcl

This is ManKai Common Lisp 1.1.8

Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
Copyright (C) 1993 Giuseppe Attardi
Copyright (C) 2000 Juan J. Garcia-Ripoll
Copyright (C) 2010-2014 Jean-Claude Beaudoin

ManKai Common Lisp (MKCL) is free software,
and you are welcome to redistribute and/or
modify it under the terms of the GNU LGPL.
See file 'Copyright' in the source code for details.

Type :h for Help.
Top level in: #<thread "Initial" active (1003) 0xb7754940 08dd4800>.
>

やれやれ。

ConEmu

パソコンを起動してる間ほとんどの時間をvboxかVMwareの上で過ごしている。だって、Win上 では開発環境が貧弱過ぎるから。その際たるものがコンソール。やる気零のM$に従うのは 勘弁って訳。

でも、最近はWindows標準のコマンドプロンプトウィンドウをタブ化できる「ConEmu」 があるみたい。これで少しはWin上に止まれるかなあ。おいらは根っからのCUI人ですから。