Gambit

『裸はいつから 恥ずかしくなったのか』(新潮選書)なんてのを読んだ。そう、この所読書三昧 なんです。勿論、紙本です。電子リーダーをこぞってメディアは取り上げているけど、そういう ものは狭い東京に住む人達のアイテムだと思うぞ。

通勤電車の中で手軽に読めるのが売りだろうけど、こちらの田舎は移動と言ったら、もっぱら自分の 足か車。歩きながら本を読むと、現代の二ノ宮金次郎かと間違えられそうだし、車を運転しながら 本読むって事も無いしね。電子リーダー推進派のrubyの人の弁によると、読み上げもしてくれる らしいから、運転しながら、聞書なら出来るかもしんないけど。

で、件の本、タイトルに引かれて読んでみたんだ。江戸時代、混浴は普通に行われていたらしい。 坂本竜馬は女房と共に、訪ねて来た友人と風呂に行ったとか。勿論混浴。これぞ本当の裸の付き合い。 こういう羨ましい習慣が無くなったのは、明治政府の弾圧によるもの。全く、お上ってのは、余計な 事をしてくれるものだ。

ペリーとかの外国な連中がやって来て、信じられない蛮習、恥ずかしくないのかとさかんに吼える ものだから、国際社会の一員になるには、この習慣を改めなければならないと、強圧な取り締まり に出たそうだ。

こういうのって、韓国で昔、犬を食べる習慣をソウルオリンピックを期に禁止したのに似てるな。 何も、西洋の習慣を押し付けなくていいと思うのに。

そもそも、昔の人は恥ずかしくなかったのか? 裸は顔の延長にあるので隠す事は必要無かった そうなんだ(ジロジロ見るのは礼儀違反だけど)。そもそも隠すと覗きたくなるってのが心理の内にあるからね。裸は性に結び付く、 だから隠せってのが(キリストを根源とする)西洋思想。

隠すよりオープンにしちゃえば変な妄想生まないでしょ、ってのが日本の思想。弾圧により西洋 思想が普遍化してくと、それが度を越し、下着も(恥ずかしいから)隠す対象になる。隠すから、 iphoneで盗撮ってのが出てくるんだな。西洋思想の負けだと思うぞ。

最近、サウナの混浴がドイツあたりで流行っているらしい。裸になれば人類皆兄弟。 そろそろ、海外旅行で体験してきたいな。それとも、秘境で混浴? 混浴で探すと、混浴日帰りとか 混浴東北とか、いっぱい出てくる。みんな江戸時代にタイムスリップしたいんだな。

OpenBSD 5.2

最近出たやつ。FreeBSDと違って、ずっと定期的に版を重ねている。ある人曰く

NetBSDからTheoを移植したものが The OpenBSD

とか。強力な親分が居るからこその偉業なのでしょう。世間では、選挙対策用の政党が乱立して、 選挙が過ぎれば、国会は波乱含みで何も決められない。時には、Theoみたいなリーダーシップも 必要と思うぞ。

で、今まで使っていた5.1を水に流して、5.2にしてみた。5.1の時は、Diskを細切れに分割したけど 、今回は大部屋方式にした。もういいってぐらいにpkg(と、ソース)を入れた状態で、

$ df -k
Filesystem  1K-blocks      Used     Avail Capacity  Mounted on
/dev/wd0a    18062286   3908016  13251156    23%    /

こんなものだ。動いているプロセスも

$ ps awx
  PID TT  STAT       TIME COMMAND
    1 ??  Is      0:01.08 /sbin/init
21065 ??  Is      0:00.06 dhclient: vic0 (dhclient)
 2476 ??  Is      0:00.01 syslogd: [priv] (syslogd)
  264 ??  S       0:00.31 /usr/sbin/syslogd -a /var/www/dev/log -a /var/empty/dev/log
11648 ??  Is      0:00.02 /usr/sbin/sshd
15970 ??  Is      0:00.01 /usr/sbin/inetd
 2694 ??  I<s     0:00.00 /usr/bin/sndiod
21652 ??  Is      0:00.04 /usr/sbin/cron
 6379 ??  Is      0:00.27 sshd: sakae [priv] (sshd)
14057 ??  S       0:01.14 sshd: sakae@ttyp0 (sshd)
12155 ??  Rs      0:00.30 SCREEN (screen)
26803 p0  Is      0:00.02 -ksh (ksh)
23705 p0  S+      0:00.07 screen
10984 p1  Ss      0:00.11 /bin/ksh
 2107 p1  R+      0:00.00 ps -awx
15213 p2  Ss+     0:00.03 /bin/ksh
 6234 C0- I       0:00.07 dhclient: vic0 [priv] (dhclient)
22081 C0  Is+     0:00.01 /usr/libexec/getty std.9600 ttyC0
  737 C1  Is+     0:00.01 /usr/libexec/getty std.9600 ttyC1

こんなものぐらいで、非常にすっきりしてる。OpenBSDの気配りとして、PIDがランダムに選ばれてる のが見て取れる。

pkgはFreeBSDの24000個に比べ7500個ぐらいと少な目だけど、普段使ってるのはほとんどカバー してくれているな。唯一無かったのが、lv。これは自前でコンパイルした。

gcc  -o lv itable.o ctable.o uty.o istr.o stream.o file.o guess.o decode.o encode.o escape.o iso2022.o iso8859.o iso2cn.o iso2jp.o iso2kr.o kana.o eucjapan.o shiftjis.o big5.o hz.o raw.o fetch.o screen.o command.o display.o find.o re.o nfa.o dfa.o conv.o version.o conf.o lv.o console.o guesslocale.o utf.o unimap.o unirev.o -ltermcap
command.o(.text+0x6c6): In function `CommandEdit':
../src/command.c:564: warning: strcpy() is almost always misused, please use strlcpy()
conf.o(.text+0x948): In function `Conf':
../src/conf.c:390: warning: strcat() is almost always misused, please use strlcat()
file.o(.text+0x1ef): In function `FileStatus':
../src/file.c:505: warning: sprintf() is often misused, please use snprintf()

そしたら、何やらエラーのようなものが。。。良く見たら、教育的指導でしたよ。とかく文字関係の 扱いでセキュリティーホールに成りやすいからね。 文字操作と入出力ライブラリーの使い方でも 注意を喚起してましたよ。

最近のOpenBSDでは、日本語も扱えるようになったらしい。ググル様が検索窓で教えてくれた。 剛力彩芽 と入力すると、かわいい、かわいくない、ごり押し とか出てきてすっかり社会の窓 状態だもの。 OpenBSDでも人気語が出ても不思議じゃないか。

話が逸れた。一押しは、 30分でできる OpenBSD 日本語デスクトップ環境 だ。おいらも乗せられてしまって、ググル謹製のブラウザーを入れちゃったよ。でも、文字化け するんだな。何で? 拡張設定でフォントを確認したら、西洋フォントになってた。フォントに 困っちゃうわ。(と、身も心も凍る親父ギャグを噛ましておこう)

Gambit

pkgの数が少ないと、カタログを舐めるように見ていくのが可能だ。で、面白いのに出会った。 そちの名は、Gambit。以前、何処かでお会いしませんでしたっけ? 思い出した、Macをやってた 時代に使ったな。

詳細は、

$ cat /usr/ports/lang/gambit/pkg/DESCR
The Gambit Scheme system is a complete, portable, efficient and reliable
implementation of the Scheme programming language.

The Gambit-C system conforms to the R4RS, R5RS and IEEE Scheme
standards.  The full numeric tower is implemented, including: infinite
precision integers (bignums), rationals, inexact reals (floating point
numbers), and complex numbers.

やっぱりそうか。コンパイルも出来るSchemeだな。これって、chickenの対抗馬だな。ここで会ったが 百年目、是非入れなければ。

入れたはいいけど、どうやって起動するんだ? こういう時は、

$ pkg_info -L gambit
Information for inst:gambit-4.6.6

Files:
/usr/local/bin/gambc-cc
/usr/local/bin/gambc-doc
/usr/local/bin/gsc
/usr/local/bin/gsc-script
/usr/local/bin/gsi
/usr/local/bin/gsi-script
/usr/local/bin/scheme-ieee-1178-1990
/usr/local/bin/scheme-r4rs
/usr/local/bin/scheme-r5rs
/usr/local/bin/scheme-srfi-0
/usr/local/bin/six
/usr/local/bin/six-script
   :
/usr/local/man/man1/gsi.1
/usr/local/share/doc/gambit-c/gambit-c.html
/usr/local/share/doc/gambit-c/gambit-c.pdf
/usr/local/share/doc/gambit-c/gambit-c.txt
/usr/local/share/emacs/site-lisp/gambit.el

糸口は、man gsi あたりからか。そしておもむろに起動。

$ gsi
Gambit v4.6.6

> ,?
,?              : Summary of comma commands
,h   | ,(h X)   : Help on procedure of last error or procedure/macro named X
,q              : Terminate the process
,qt             : Terminate the current thread
,t              : Jump to toplevel REPL
,d              : Jump to enclosing REPL
,c   | ,(c X)   : Continue the computation with stepping off
,s   | ,(s X)   : Continue the computation with stepping on (step)
,l   | ,(l X)   : Continue the computation with stepping on (leap)
,N              : Move to specific continuation frame (N>=0)
,N+  | ,N-      : Move forward/backward by N continuation frames (N>=0)
,+   | ,-       : Like ,1+ and ,1-
,++  | ,--      : Like ,N+ and ,N- with N = nb. of frames at head of backtrace
,y              : Display one-line summary of current frame
,i              : Display procedure attached to current frame
,b   | ,(b X)   : Display backtrace of current continuation or X (cont/thread)
,be  | ,(be X)  : Like ,b and ,(b X) but also display environment
,bed | ,(bed X) : Like ,be and ,(be X) but also display dynamic environment
,e   | ,(e X)   : Display environment of current frame or X (proc/cont/thread)
,ed  | ,(ed X)  : Like ,e and ,(e X) but also display dynamic environment
,st  | ,(st X)  : Display current thread group, or X (thread/thread group)
,(v X)          : Start a REPL visiting X (proc/cont/thread)
>
*** EOF again to exit

で、ここからどうしろと? まずは、manに乗ってたHomePageへ行ってみる。 gambitって、マスコットは 馬さんなんですか。辞書で単語を調べたら、チェスの序盤の手とか手始めとかが出てきた。数学の手始めにどうぞって 事だな。

そして、 Gambit Schemeの作者Marc Feeley教授が同言語の実装に関するプレゼンを出した から参照出来る、作者様のプレゼンが非常に参考になります。 また、HomePageでは、ipadでも動くよーって言ってて、やっぱり、生まれはアプルって実感させられますなあ。

まずは、お約束なやつ。hello.scm

(display "Hello Gambit")
(newline)

インタープリタで、まったりと実行

$ gsi hello.scm
Hello Gambit

動いているな。それじゃ、コンパイルしれ。

$ gsc -verbose fib.scm
Parsing:
  "declare"
  "declare"
  "declare"
  "declare"
  fib
  "expr"
  "expr"

Compiling:
  fib

Dumping:
  #<primitive | fib.o1|>
  #<primitive fib>

Compilation finished.
*** ERROR IN ##compile-file -- Unimplemented operation
(open-process
 '(path: "/usr/local/bin/gambc-cc" arguments: ("dyn") directory: "/home/saka...)

どうも旨く行かない。dynって、OpenBSDでサポートしてたっけ?よう知らん。マニュアルを ごそごそしてたら、上記のフェーズを分解して実行プログラムを作成する例が出てた。

それをまとめればいいんだな。専用のMakefileを書くべきか? それとも汎用の コマンドの集まりにしておくか? 3秒考えて、今日の所はshellスクリプトにしとく。名前は、 期待を込めて、speedってしとく。turboの方が良かったかも。

#!/bin/sh
# Usage: speed foo.scm

rm -f runme *.c
gsc -c $1
gsc -link $1
gcc -O3 -o runme -L/usr/local/lib/gambit-c -I/usr/local/include/gambit-c *.c -lgambc -lm  -lutil

ゴミ掃除のrmは最後の方が良いと思われるけど、残骸を調べるのも楽しそうなので、残るように しとく。それから、問答無用でCのソースを消してるんで、そこら辺は自己責任でね。

$ ./runme
Hello Gambit

ちゃんとバイナリーが実行出来た。で、その中身は? まずは外見とか。

$ ls -l runme
-rwxr-xr-x  1 sakae  sakae  7839 Dec  4 15:50 runme
$ ldd runme
runme:
        Start    End      Type Open Ref GrpRef Name
        1c000000 3c004000 exe  1    0   0      runme
        076de000 27818000 rlib 0    1   0      /usr/local/lib/libgambc.so
        0f87d000 2f886000 rlib 0    2   0      /usr/lib/libm.so.7.0
        0374a000 2374e000 rlib 0    2   0      /usr/lib/libutil.so.11.3
        02079000 220a7000 rlib 0    1   0      /usr/lib/libc.so.65.0
        0c5d5000 0c5d5000 rtld 0    1   0      /usr/libexec/ld.so

環境依存は、libgambc.soだけだな。そんじゃ、ごみと言うか中間ファイルを見る。*.scmをコンパイル すると、*.c が出来、-link で、ライブラリー類と接続用の *_.c が出来るんだ。

この場合だと、前者がhell.c、どうもC言語的に言うと、マクロっぽい仕上がりになってる。 後者は、hello_.c になり、ヘッダーにはリンカー情報って書いてある。何だか、oblistっぽい 内容が永遠と続いてたよ。これを見れば、gambitがどんな手続きを持ってるか、きっと分かるよ。

能書きはともかくとして、早速のspeed違反ぶりを見てみる。題材はお馴染みのフィボナッチ。 何せ、自然界はフィボナッチで満たされているからね。(巻貝の螺旋具合とかひまわりの花弁の具合、等々)

フィボナッチ数の小宇宙(日本評論社)なんて本を読むと、フィボナッチ数の親戚としてリュカ数 なんてのも有るのね。前者は、種として(1,1)からスタートするけど、後者は(1,3)からスタート するそうな。なかなか歯ごたえがあって面白い世界だぞ。女王陛下本は素数を題材にしてるようだ けど、フィボナッチ数は出てこないのかな?

フィボナッチ数 をみて、フィボナッチ協会経由で、 Custom Fibonacci Spiral Generatorなんてのが有ったよ。

(declare (standard-bindings))
(declare (block))
(declare (fixnum))
(declare (not safe))

(define (fib n)
  (if (< n 2)
      n
      (+ (fib (- n 1))
         (fib (- n 2)))))

(print (fib 40) "\n")
(exit)

まずは、遅いやつ。

$ time gsi fib.scm
102334155
    4m52.05s real     3m11.07s user     1m40.42s system

真剣にスピードを出すと、こうなります。が、違反にはなりませんでした。

$ time ./runme
102334155
    0m1.25s real     0m1.20s user     0m0.03s system

スピードアップの秘訣は、冒頭にある宣言文により、こういう事みたいです。

   (declare (standard-bindings)) carなどの標準の関数などをインラインさせる。
   (block) ファイル内のグローバル変数はそこ以外で変更されないという約束
   (fixnum) (flonum) 演算の際、変数のタイプを指定する?
   (not safe) タイプチェックを省く
   (not proper-tail-calls) tail callしなくてもいい

猛一つベンチします。世間でよくあるたらい回しです。あっちの窓口、こっちの窓口ってね。 それを具現化した、あの先生に敬意を込めて!

$ cat tarai.scm
(define tarai
    (lambda (x y z)
      (if (<= x y)
        y
        (tarai
                (tarai (- x 1) y z)
                (tarai (- y 1) z x)
                (tarai (- z 1) x y)))))

(print (time (tarai 12 6 0)) "\n")
(exit)
$ gsi tarai.scm
(time (tarai 12 6 0))
    11597 ms real time
    7940 ms cpu time (3940 user, 4000 system)
    4114 collections accounting for 1203 ms real time (100 user, 690 system)
    605033328 bytes allocated
    24 minor faults
    no major faults
12

11.6秒かかったのか。gaucheはどうかな? OpenBSD5.1の時、コンパイルしてみたら、エラッて しまったんだが、無理して突っ込んだ記憶がある。shiroさんは新しい版に向けてやる気モード に入ったみたいだから、おらいもお願いモードに入ろうかな。

$ ./runme
(time (tarai 12 6 0))
    314 ms real time
    220 ms cpu time (220 user, 0 system)
    no collections
    no bytes allocated
    2 minor faults
    no major faults
12

コンパイルしちゃうとガベコレが発動しないけど、どういう仕組みになってるの? プレゼン資料に書いてあるのかなあ?