shibuya.lisp#4 から oreore_lisp

おいらは、毎日、近くのスーパーへ水を汲みに行くのが日課となっている。残念ながら 養老の滝でも不老長寿の水じゃなくて、純水と言うのが残念である。 昔、韓国に駐留してた時は、下宿先の近くに湧き出る、不老長寿の水をよく飲んだものである。

で、このスーパーの水汲み場が結構混雑していて、時間帯によっては行列が出来ている。 とある日、行列に並んでいたら、私の後ろにベビーカーを引いた若いお母さんが。

ベビーカーに乗った子供を見るとは無しに見ると、どうやら、おいらを興味深そうに見ている。 こりゃ、ちょっと挨拶してあげるかな。えっと、坊や?お嬢ちゃん? どっちだろう。服装とか では区別出来そうになかった。

こういう時は、とりあえず お嬢ちゃん と声を掛けるのが大人の対応ってもんだ。で、声を 掛けてみた。「お嬢ちゃん、幾つ?」すると、もみじのような指が2本出てきた。同時に、 恥ずかしいのか、ぱっと横を向いてしまった。でも、やっぱりおいらの事が気になるみたいで チラチラと見ている。

お母さんは、「はにかみ王子で、困ってしまいます」と、その場を取り繕ってくれた。 ありゃ、こりゃ失礼しました。そのお母さんが言う事にゃ、余り外にも出る事がなく、いろいろ な人を見る事も、ましてや知らない人に声を掛けられる事もないので、戸惑っているんでしょう との事。 いろんな人に接して、早く免疫を付けてくださいな。

そういえば、私の住む長屋の子供は、免疫が出来たみたいで、おいらを見ると、「おじちゃん」 と言って、寄ってくるようになったよ。

Gauche-0.9_rc2 time

前回は、AM-Schemeの怪しいmacroを見た。果たして、あのようなマクロで良かったのだろうか? 幾ら考えても分からないので、我らがgaucheでは、どうなっているか、ちと覗いてみる。

解禁まじかのボージョレヌーボーならぬ、今年の新米ならぬ、Gauche-0.9_rc2のソースが手元で 展開されているので、肴にする。

えーと、timeは何処か探してみると、Gauche-0.9_rc2/lib/gauche/time.scmがズバリのものだ。

(define-syntax time
  (syntax-rules ()
    ((_ expr . exprs)
     (let*-values (((stimes) (sys-times))
                   ((sreal-sec sreal-msec) (sys-gettimeofday))
                   (r (begin expr . exprs))
                   ((etimes) (sys-times))
                   ((ereal-sec ereal-msec) (sys-gettimeofday)))
       (format (current-error-port)
               ";~,,,,75:s\n; real ~a\n; user ~a\n; sys  ~a\n"
               '(time expr . exprs)
               (format-delta-time
                (- (+ ereal-sec (/. ereal-msec 1000000))
                   (+ sreal-sec (/. sreal-msec 1000000))))
               (format-delta-time
                (/. (- (list-ref etimes 0) (list-ref stimes 0))
                    (list-ref stimes 4)))
               (format-delta-time
                (/. (- (list-ref etimes 1) (list-ref stimes 1))
                    (list-ref stimes 4))))
       (apply values r)))
    ((_)
     (syntax-error "usage: (time expr expr2 ...); or you meant sys-time?"))
    ))

どうやら、新方式のマクロで定義されてるな。でも、言わんとしてる事は分かる。(let*-values ... )内 で、計測して、format 節で、結果の実行時間を表示、最後に、与えた式の結果を表示かな。 ちと、実例をば。

[sakae@nil ~]$ rlwrap mine/bin/gosh
gosh> (define (fib n)
        (if (< n 2)
            n
            (+ (fib (- n 1)) (fib (- n 2)))))
fib
gosh> (time (fib 20))
;(time (fib 20))
; real   0.003
; user   0.000
; sys    0.000
6765

コードを感じられると、嬉しいものだ。書けと言われると、一発では賭けないけど。 上で出てきた、sys-times、sys-gettimeofdayは、想像つくけど、一応確かめてみる。

gosh> (sys-times)
(10 39 0 0 128)
gosh> (sys-gettimeofday)
1257739559
720698

sys-timesっていろいろ帰ってくるけど、何を表しているん? gauche-refjしたら、POSIXと言われて 、man 3 times したら。

           struct tms {
                   clock_t tms_utime;
                   clock_t tms_stime;
                   clock_t tms_cutime;
                   clock_t tms_cstime;
           };

     この構造の要素は、次のように定義されます:

     tms_utime   ユーザインストラクションの実行に対して請求される CPU タイム。
     tms_stime   その処理のためのシステムによる実行に対して請求される CPU タイム。
     tms_cutime  子プロセスの tms_utime s および tms_cutime s の和。
     tms_cstime  子プロセスの tms_stimes および tms_cstimes の和。

     すべての時間は、 CLK_TCK 秒で表されます。

って、言われたけど、最後の要素は、FreeBSDでは定義されてない。こりゃ、潜れって事ですかね。 面倒そうなので止めるけど、その使われ方からすると、実時間に直す為の基数だな。そういう 事にしておこう。

で、残る、sys-gettimeofday は、多値で帰ってくるのね。1257739559ってEPOC秒。

[sakae@nil ~]$ date -r  1257739559
Mon Nov  9 13:05:59 JST 2009

date の -r オプションって、FreeBSDだけだったかな? Linuxerは、rubyで軽く、

[sakae@nil ~]$ cat cvtime
#!/usr/local/bin/ruby
t = ARGV.shift || Time.now
puts Time.at t.to_i

[sakae@nil ~]$ ./cvtime 1257739559
Mon Nov 09 13:05:59 +0900 2009

嗚呼、久しぶりにrubyコードを書いた象! たった、2行だけど。

また、投書を頂いた象

親切な読者の方から、また投書を頂いた。いつもありがとうございます。本来なら、はてな? あたりで流行りのブログにでもすれば、お手を煩わせる事が無い事は、承知してますが、なに分 、古い人間でして、お許しください。

まず、こんなマクロを定義してみて下さい。

(macro id (lambda (body) `',body))

実際にやってみると

> (macro id (lambda (body) `',body))
id
> (id hoge)
(id hoge)

なんか、皮剥きが足りないようですね。

つまり、 body に入っているのは (id a) という形のリストなのです。
記事中で定義しているマクロ time の場合だと (time (fib 10)) と
書けば、それは

(let ((st (gtod)))
  (time (fib 10))
  (- (gtod) st))

と展開されてしまいます。 どうしてエラーメッセージが Unbound
variable f なのかはよくわかりませんが。

エラーになるのは、再帰が起こって、メモリーを食い潰し、gc()やっても 間に合わなくなって、暴走。resetが怒ったというパターンですね。 長年付き合っていると、AM-Schemeの性格が読めてきました。(笑)

> (gc-verbose #t)
#t
> (time "foo")
gc...done. 217368 bytes are free.
gc...done. 215672 bytes are free.
Error: Unbound variable level
[return to toplevel]

と言う事で、AM-Schemeは、my-stackに積んで、少し冷却する事にします。変わりに 未だ、興奮さめやらぬ shibuya.lisp#4 の教材で遊んでみる事にします。遊び 飽きたら、my-stackからpopしてconinueしたいと思いますが、その間に gc()が 入って、stackが破壊されてたら、笑ってお許し下さい。

shibuya.lisp#4の教材から

shibuya.lisp#4のために、吉田さんことyuumi3 さんが 用意された教材がある。 テキストサンプルコード内に、yuumi3が書かれた oreore_lispと言うTiny Lispがあるので これで、しばし遊んでみる。

[sakae@nil ~/oreore_lisp]$ wc *
      12      26     169 Makefile
      24      90     529 base.lisp
     859    2657   22987 oreore_lisp.c
     895    2773   23685 total

本当にちっちゃい。本体は、859行となっているが、後半部分は、テストコードになっている ので、実質、620行ぐらいだ。ちと、改造とかもしたくなるに違い無い。

ならば、以前にやった git 一人 するかなと思ったのだけど、ちと大袈裟過ぎる事に 気づいてしまったのだ。だから、、、

RCS の登場

RCSに登場してもらおう。RCSって何よ。また、爺のざれ言かと言うなかれ。

RCS -> CVS -> SVN -> GIT

っつう事で、Lispに例えるなら、Lisp 1.5 みたいなもんだな。

man rcsintro とやると、簡単な説明が出てきます。

[sakae@nil ~/oreore_lisp]$ mkdir RCS
[sakae@nil ~/oreore_lisp]$ ci Makefile
RCS/Makefile,v  <--  Makefile
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>> Original
>> .
initial revision: 1.1
done
[sakae@nil ~/oreore_lisp]$ ci base.lisp
  :
[sakae@nil ~/oreore_lisp]$ ci oreore_lisp.c
  :
[sakae@nil ~/oreore_lisp]$ ls
RCS/

倉庫としてRCSを用意し、管理したいファイルを、ci コマンドを使って登録します。登録時に 説明文を求められるので、指示に従います。そうすると初期Verとして、1.1が与えられて、倉庫に 格納されてしまいます。以下管理したいファイルを同様に登録します。今3つのファイルを 登録しちゃいましたので、元dirは空になりました。

さて、編集をする目的で倉庫からファイルを取り出します。

[sakae@nil ~/oreore_lisp]$ co -l Makefile
RCS/Makefile,v  -->  Makefile
revision 1.1 (locked)
done
[sakae@nil ~/oreore_lisp]$ co -l base.lisp
RCS/base.lisp,v  -->  base.lisp
revision 1.1 (locked)
done
[sakae@nil ~/oreore_lisp]$ co -l oreore_lisp.c
RCS/oreore_lisp.c,v  -->  oreore_lisp.c
revision 1.1 (locked)
done
[sakae@nil ~/oreore_lisp]$ ls
Makefile        RCS/            base.lisp       oreore_lisp.c

これで、編集用にロック付きで取り出されました。ロックがかかったファイルは、他の人は 編集できません。

さて、Makefileをちょっといじって、作成されるオブジェクト名を変更しました。 どういう変更をしたかと言うと

[sakae@nil ~/oreore_lisp]$ rcsdiff Makefile
===================================================================
RCS file: RCS/Makefile,v
retrieving revision 1.1
diff -r1.1 Makefile
7,9c7,9
<       $(CC) -g -o $@ $(SRCS) -l$(LIBS)
< test: oreore_lisp
<       ./oreore_lisp test
---
>       $(CC) -g -o yuumi3 $(SRCS) -l$(LIBS)
> test: yuumi3
>       ./yuumi3 test
12c12
<       rm -f oreore_lisp
---
>       rm -f yuumi3

yuumi3の名前にしました。って、慣れないと、読むの大変ですね。

[sakae@nil ~/oreore_lisp]$ ci Makefile
RCS/Makefile,v  <--  Makefile
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single '.' or end of file:
>> Change object name
>> .
done
[sakae@nil ~/oreore_lisp]$ ls
RCS/            base.lisp       oreore_lisp.c   yuumi3*

変更が終わったので、また倉庫に仕舞いました。後は、この繰り返しですね。 そんじゃ、遊び方を考えてみますね。