Let's start Scheme

2011-09-29

9月が終わる

10月3日はライデンの80年戦争終了記念日(だよな・・・?)
毎年この時期になると街はお祭り準備でバスやらの公共交通機関が半分麻痺状態になる。まぁ、職場はロッテルダムなのでライデンのバスはあんまり使わないんだけど。

今年で3度目。もう少しで今年も終わり。う~ん、一年は短い。もっといろいろやりたかったんだけどなぁという気もしているが、あと2ヶ月でどこまでできるか?

なんとなくお祭り前夜をみて思った。

2011-09-24

call/cc実装論文

Chez Schemeに使われている(らしい)call/ccの実装論文を読んでいるのだが、これで動く理由が分からない。
正確にはこれをSagittariusに適用できるか分からないか。

これが正しい理解かは微妙だが、大雑把に言えば継続が捕捉された時点のスタックポインタ以前のスタックを凍結、スタックフレームに以前のスタックポインタを足す。っで、捕捉された継続が呼び出されたら凍結されたスタックを現在のスタックに置き換える。
確かにこの方法なら作成時にスタックのコピーが無いので作成はほぼノーコスト。でもこれってcall/ccから脱出するとき困らんかな?
call/ccから脱出するときにどうしてもスタックのアンダーフローが検出されるので捕捉された継続を戻す必要がでる気がする。それともなんらか別の方法でその辺は何とかしてるのかな?

思考レベルだがこれを適用する際に問題になりそうなのは積みかけのフレームだと思ってる。例えば以下のケース:
(+ 1 (call/cc (lambda (c) 2)) 3)
というのがあったとして、call/ccが呼ばれた際のスタックは以下のようになる。(呼ばれた時点で、call/ccに渡されたlambda内ではない)
+-----------------+ <-- sp
| (lambda (c) 2)  |
+-----------------+ <-- fp
| Frame(call/cc)  |
+-----------------+ 
|       1         |
+-----------------+
|  Frame(+)       |
+-----------------+
Sagittariusでは上記のすべてが別ヒープにコピーされて、継続が呼び出された際にスタックに戻される。スタックVMで実装する際の一番重たい実装方法だ(よね?)
っで、上記の論文を考えると、数値2が返された段階でアンダーフローが検出される。その際上記のスタックは凍結されているので動かせない、つまり新スタックフレームに既に積まれた数値1とFrame(+)を積む必要がある。
あぁ、アンダーフローが検出された際って新スタックフレームは空であることが保障されているのでフレームポインタのことを考えなければ単にコピーするだけか。ヒープ割り当ててコピーする処理がコピーだけになったと思えば、悪くないだろうか?
理想としてはcall/ccの呼び出しで捕捉された継続が呼び出されないと分かっているなら(上記の例みたいな)、スタックを凍結せずそのままってのが一番だわな。この辺はコンパイラに頼るほかないが。

ブランチ切ってやってみるか。

2011-09-19

結局

Display closureをスタックに移すとcall/ccが激重になることが分かったので、ちょっと整理する程度にとどめた。おかげでインストラクションの意味がかなりすっきりしたと思う。
Gambitのベンチマークもbrowseとctakを除けばほぼmoshと同等かそれ以上に数値を記録しているのでまぁいいだろう。
(GaucheとYpsilonが異次元の速さなのはなぜだ?)

中身がだいぶ変わったし、マクロの書き換えもしたということで、ドキュメントの整備が終わったら2.0としてリリースしてしまおう。(このタイミングでもないと1.xのまま突き進みそうだし)
その間にcall/ccの高速化もしたいが、まぁ無理だろう。

2011-09-17

日本人がオランダに長く居すぎてしまったと感じるとき その2

調子にのってというかふと思いついたのでその2。
  1. 財布の中に20ユーロ入っていればOKと思うとき
  2. 雨が降っても傘をささないとき
  3. ビデオレンタル屋でAVがワゴンで売られていてもなんとも思わないとき
  4. etos(日本で言う杉薬局みたいなの)に大人の玩具が置いてあってもなんとも思わないとき
相変わらず思いつかなかった。解説が必要なのはは1かな?
ATMカードがあれば大抵の場所で支払いOKなので、そんなに持ち歩かなくてもいいんです。英語はDebitだったかな?オランダではPINっていいます。

いきなり雨に降られて濡れ鼠になりつつビデオレンタル屋にいったのでふと思いついた。AVはマジでワゴンで売られてます(普通の本屋にもあるという)。でもレンタル用のコーナーは一応分けられてる不思議。

2011-09-16

とりあえず

boyerが走るくらいの物まではできた(R6RSのテストはSEGVる)。
結果としては2倍から速く、GCも12回と明らかに違う。やる価値はありそうだ。

ここで問題が一つ。
今までヒープに置いていたものをスタックに置くようにしたのでものすごい勢いでスタックを食いつぶす。let*とか使ってると悲惨なことになる。さらにスタックの拡張が不完全だったというのもあり食いつぶすとSEGVる。
スタックの拡張については別に見直す必要があるが(おそらくcall/ccもだろう、うぅ・・・)、それより前に不要なDisplay closureの削除をしたい。
とりあえず思いついたのが、POP_LET_FRAMEされて且つSHIFTJでジャンプしないものはdisplay closureを辿る必要がないので削れそう。
作成時にリンクさせてしまうので、DISPLAYインストラクションにそれが末尾かどうか知らせる必要があるか。
ジャンプがあるかどうかはMARKインストラクションでマークされたdisplay closureがあればジャンプされる可能性があるとすればいいだろう。

スタックの拡張はちょっと考えないとなぁ。保存する前にごちゃごちゃやるとかだろうか?

2011-09-15

Display closureをスタックに置きたい

さすがの遅さにいらいらしたのと、これを解決しないとGaucheやYpsilonに手も届きそうにないので。

事の発端。
Gambitのベンチマークにboyerというのがあるのだが、これの速度が半端なく遅い。(さらに遅いのにbrowseがあるが、原因は一緒だろう)
あまりの遅さにGaucheの統計情報にGC回数を追加してビルドしたものと比較してみた。
GC回数脅威の320回!!!
(ちなみに、Gaucheは8回くらい)
3桁超えてきたかという感じ。

原因は以前も書いたDisplay closureで、letが連なってかつ外側のletの変数を参照してると作られる。要するに自由変数を解決するための仕組み。
これを毎回作っていたのではメモリによろしくないことが数字で出てしまっているので、なんとかスタックに作れないかなぁと試行錯誤中。

メモ:

  1. Display closureはインストラクションDISPLAYで作成される。
  2. DISPLAYは必ずLET_FRAMEの下に現れる。
  3. letが末尾呼び出しならPOP_LET_FRAMEでフレームは取り除かれる
  4. 3以外なら、ENTERとLEAVEが呼び出される
スタックにつむためには以下のことを考える必要がある。

  1. スタック領域に場所を確保し、積み上げた自由変数を移し変える
  2. 空いた場所にスライドさせる
  3. POP_LET_FRAMEが呼ばれた際にスタックにあるDisplay closureを移動させ、フレームポインタを移動させる
  4. LEAVEではDisplay closureが作られていたら除去する必要がある
ここまでやったがうまく動かない。どこかに見落としがある。どこだろう?

2011-09-14

私がSpring Webflowを使いたくないいくつかの理由

いい加減腹立ってきたわ、この糞仕様に!!

ということでどこがまずいか、どうして使ってはいけないかを書き出してみる。(だからといって現状が変わるわけではなく、単なる愚痴である)
  1. スコープまたぎができない
    • これは以前書いたけど、Ajaxとの親和性が悪すぎる
  2. とりあえずデバッグレベルですべてのデータを吐き出す
    • パスワードとか見せたくない(これも以前書いた)
  3. Default***クラスを直接newしてる
    • Defaultそのまま固定です。ユーザーは振る舞いをカスタムできません。
  4. Modelを使わないと入力チェックが非常に面倒になる
    • 2と3番の問題でフォームデータ直接チェックしたくなったけど、どうも無理臭い
  5. 設定ファイルの記述がドキュメントにほとんどない
    • カスタムはあまりするなということか?
  6. そのくせデフォルトの設定はあまりにひどい
    • 主に2,3,4番だわね
めんどくさくなったので、これくらい。使えば使うほどげんなりするのも仕様です。ってか、ほかのプロジェクトとかどうしてるんだろう?特に2番。
リリース後はデバッグログなんて出さないのかな?パッケージソフトには厳しいお言葉過ぎるよ。

ライブラリのインライン展開

1つのライブラリを最適化できないかなぁと思って、とりあえずインライン展開を試みてみた。
(大別するとグローバル最適化?でも、R6RSだとライブラリは1つのS式だから、そうでもないか)

とりあえず試したのは以下のこと。
exportされていない関数でかつ非再帰、相互参照なし、ライブラリ内で代入されていないものを抽出。
最適化時に上記の関数でかつそこそこサイズが小さいものをインライン展開。
たったこれだけ!

1個の巨大なS式と思えばまぁこんなものだろう。
で、効果があるのかちょっと検証。
以下のプログラム。
(library (test)
    (export process set-parameter!)
    (import (rnrs))

  (define *paramter* #f)

  (define (set-parameter! param)
    (set! *paramter* param))

  (define (get-paramter name default)
    (or (and *paramter* (hashtable-ref *paramter* name default))
         default))

  (define (get-count)
    (get-paramter 'count 1))

  (define (get-process)
    (get-paramter 'process (lambda args args)))

  (define (get-args)
    (get-paramter 'args #f))

  (define (process)
    (let ((n (get-count)))
      (let loop ((i 0))
    (unless (= i n)
      (let ((proc (get-process))
        (args (get-args)))
        (apply proc (list args)))
      (loop (+ i 1))))))
)


(import (test))
(define param (make-eq-hashtable))
(hashtable-set! param 'count 500000)
(hashtable-set! param 'args '(a b c d e f))
(hashtable-set! param 'process (lambda (a . b)
                 (fold cons a b)))
(set-parameter! param)
(time
 (process)
)
ちょっと作為的過ぎるだろうか?イメージとしてはオブジェクト指向のプロパティな感じということで。

実際にインストラクションのダンプを取るとprocessの中にget-count、get-process、get-argsの姿はない。

次に速度を比較。
インライン展開あり:
$ ./build/sash.exe -L. test.scm
;;  0.632000 real    0.641000 user    0.000000 sys
インライン展開なし:
$ ./build/sash.exe -fno-library-inline -L. test.scm
;;  0.681000 real    0.672000 user    0.000000 sys
40~50ms速いけど、50万回まわしてこの結果か。一応入れておくか程度だな。うっかりすると遅くなりそうで怖いが・・・

何より悲しいのはこれはGambitのベンチマークではまったく意味がないところか。

2011-09-12

Prefixつけたimportに潜む罠

R6RSでコード書いてて、
(import (prefix (rnrs) r6:))
って書く人はまぁいないだろう。onlyとかrenameならあるだろうけど。
これにこっそりと罠が潜んでいた。(というほどでもないんだけど)
たとえばこんなコード。
(define-syntax test
  (syntax-rules ()
    ((_ a b ...)
     (list a b ...))))
なんのことはないアホみたいなコードだ。
これを上記のprefix付で書くとこうなる。
(r6:define-syntax test
  (r6:syntax-rules ()
    ((r6:_ a b r6:...)
     (r6:list a b r6:...))))
でもこれYpsilonでは通らない。Ypsilonではこう書く必要がある。
(r6:define-syntax test
  (r6:syntax-rules ()
    ((_ a b ...)
     (r6:list a b ...))))
こうするとmosh及びnmoshでは通らない。でもPetite Chez Scheme(v 7.9.4)では通った。psyntax及びAndre van Tonderのsyntax-caseは厳格だということなのだろう。
ちなみにSagittariusも通らない。通るようにすることもできるんだけど、どうしようかなぁ?
こんなコード書かれないよなぁ・・・

Boehm GCが遅かった

Twitterで「速度が出ない」とつぶやいたが、原因が分かった。
まぁ、結論はすでにタイトルに書いてあるのだが、何が違ったかということをば。

調べたこと。
Gambitベンチマークのbrowseがやたら遅い。moshで5秒、Gaucheで1.7秒(速!)、Ypsilonで2.5秒、Sagittariusは12秒という結果だった。(Windows XP, Cygwin, Core2Duo 3.00GHz)
Display closureという構造をとっているmoshと比べても2倍遅いのはおかしいということで調査。
インストラクションの精査から始めて、結局以下のコードが遅くなることに気づいた
(do ((i 0 (+ i 1)))
     ((= i 10000)) ;; iを100000にすると遅くなる
  (cons 'a 'b))
何が問題だったか?
(cons 'a 'b)をコメントアウトするとmoshとの速度にほとんど差がでない。10000の時でもほとんど差が出ない。
ここでGCを疑う。
とりあえずGCの回数を出力してみたら、10000回だと9回で100000回だと10回になっていた。GCが遅い。

ここで出た疑問。なぜmoshでは遅くならないか?現状ではSagittariusもBoehm GCを使っている(絶対そのうち置き換えてやる!)が、Sagittariusでのみ問題になっている。
コンパイルオプションを調べた。moshのCygwinでのオプションは--disable-shared CFLAGS=-DGC_THREADS win32_threads=trueになっていた。
SagittariusはBoehm GCをバンドルしてないが、win32_threads=trueとかCFLAGS=-DGC_THREADSを渡してコンパイルした記憶がない。
上記を渡してリコンパイルしてみた。
5秒短縮!!!
その他のベンチマークもmoshと同等かそれ以上(遅いのもある)という結果になった。

原因探るのに2日かかったがこんな落ちとは正直思っていなかった。

追記:
自宅のX60ノートで同様にリコンパイルしてリンクしなおしたのだが、速度差はなかった。(上記のは会社のマシン^^;)
どうやらまだまだ別の場所に原因がありそうだ。

追記の追記:
やっぱりGCっぽい。別にコンパイルオプションがあるのだろうか?

2011-09-08

静的リンクにしておけば・・・

ベンチマークを取った際に2倍以上Gaucheに放されるテストが多数あったので原因を追求してみた。
端的にはこれ↓
(cond-expand
 (sagittarius
  (import (sagittarius compiler))
  (define flush flush-output-port)
  )
 (gauche
  (define compile-p2 (with-module gauche.internal compile-p2))
  (define compile-p3 (with-module gauche.internal compile-p3))
  )
 (else
  (exit)))

(define sexp '(define (lookup key table)
(let loop ((x table))
 (if (null? x)
     #f
     (let ((pair (car x))) ;; 【*1】ここが問題
(if (eq? (car pair) key)
   pair
   (loop (cdr x))))))))

(compile-p2 sexp)
(flush (current-output-port))
(compile-p3 sexp)
この結果が以下
$ sash -I"(srfi :0)" test.scm
($define () lookup
  ($lambda[lookup.0] (key[1.0] table[1.0])
    ($call[embed] ($lambda[loop.2] (x[3.0])
                    ($label #0
                      ($if ($asm (NULLP)
                             ($lref x[3.0]))
                        ($const #f)
                        ($let ((pair[2.0] ($asm (CAR)
                                            ($lref x[3.0]))))
                          ($if ($asm (EQ)
                                 ($asm (CAR)
                                   ($lref pair[2.0]))
                                 ($lref key[1.0]))
                            ($lref pair[2.0])
                            ($call[jump] ($call[embed] ($lambda[loop.2] (x[3.0])

                                                         label#0)
                                           ($lref table[1.0]))
                              ($asm (CDR)
                                ($lref x[3.0]))))))))
      ($lref table[1.0]))))
size: 5
0: CLOSURE #
  size: 37
  0: LET_FRAME(3) ;; (let loop ((x table)
  1: LREF_PUSH(0) ;; key
  2: LREF_PUSH(1) ;; table
  3: DISPLAY(2)
  4: LREF_PUSH(1) ;; table
  5: POP_LET_FRAME(1)
  6: MARK
  7: LREF(0) ;; x
  8: BNNULL 5 ;; (if (null? x) #f (le
  10: CONST #f
  12: JUMP 23 ;; #f
  14: LET_FRAME(4) ;; (let ((pair (car x))
  15: FREF_PUSH(1) ;; key
  16: LREF_PUSH(0) ;; x
  17: FREF_PUSH(0) ;; table
  18: DISPLAY(3)
  19: LREF_CAR(0) ;; x
  20: PUSH
  21: POP_LET_FRAME(1)
  22: LREF_CAR(0) ;; pair
  23: PUSH
  24: FREF(2) ;; key
  25: BNEQ 4 ;; (if (eq? (car pair)
  27: LREF(0) ;; pair
  28: JUMP 7 ;; #f
  30: FREF(1) ;; x
  31: CDR ;; (cdr x)
  32: PUSH
  33: SHIFTJ(1 1)
  34: JUMP -28 ;; #f
  36: RET

2: DEFINE(0) # ;; (define (lookup key
4: HALT
もう一つはGauche
$ gosh test.scm
($define () lookup
  ($lambda[lookup;0] (key[1;0] table[1;0])
    ($letrec ((loop[2;0] ($lambda[loop;0] (x[3;0])
                           ($if ($asm (NULLP)
                                  ($lref x[3;0]))
                             ($const #f)
                             ($let ((pair[2;0] ($asm (CAR)
                                                 ($lref x[3;0])))
                                    )
                               ($if ($asm (EQ)
                                      ($asm (CAR)
                                        ($lref pair[2;0]))
                                      ($lref key[1;0]))
                                 ($lref pair[2;0])
                                 ($call ($lref loop[2;0])
                                   ($asm (CDR)
                                     ($lref x[3;0]))))))))
              )
      ($call ($lref loop[2;0])
        ($lref table[1;0])))))
main_code (name=%toplevel, code=0x1043bc00, size=5, const=2, stack=0):
args: #f
     0 CLOSURE #      ; (lambda (key table) (let loop ((x table) ...
     2 DEFINE(0) #; (define (lookup key table) (let loop
 ((x ...
     4 RET
internal_closure_0 (name=lookup, code=0x1043bc18, size=6, const=1 stack=8):
args: #f
     0 LOCAL-ENV-CLOSURES(1) (#); (let loop ((x table)) (if (null? x)
#f ( ...
     2 LREF10-PUSH              ; table
     3 LREF0                    ; loop
     4 TAIL-CALL(1)
     5 RET
internal_closure_1 (name=loop, code=0x104c6f78, size=17, const=0 stack=8):
args: #f
     0 LREF0                    ; x
     1 BNNULL 4                 ; (null? x)
     3 CONSTF-RET
     4 LREF0-CAR                ; (car x)
     5 PUSH-LOCAL-ENV(1)        ; (let ((pair (car x))) (if (eq? (car pair ...
     6 LREF0-CAR                ; (car pair)
     7 PUSH
     8 LREF(3,1)                ; key
     9 BNEQ 12                  ; (eq? (car pair) key)
    11 LREF0-RET                ; pair
    12 LREF10-CDR               ; (cdr x)
    13 PUSH
    14 LREF20                   ; loop
    15 TAIL-CALL(1)             ; (loop (cdr x))
    16 RET
適当にスクロールして見てください。
一つ目の結果はそこまで変わらないのに、2つ目のインストラクションがまずいことに。
原因はSagittariusはmoshのようにDisplay closureを持っていて(これは3imp.pdfにあるやつ)、自由変数が現れると作られるのだが、この処理が重い。参照は早いが作成は遅いというもの。
Gaucheは逆に静的リンクで、作成は軽いが参照が若干重いというもの(だと思う)。
問題になるのは【*1】で示した場所で、ここでletをはさむためkeyとtableが自由変数になる。
ここで【*1】のletを削って、(eq? (car pair) key)を(eq? (car (car x)) key)とすると自由変数が無くなりちょっと処理が軽くなる。

この辺最適化でなんとかできるのかなぁ?stalinでも読むか。

2011-09-07

Fatal bug

I have checked the traffic of this blog, like from which country or which searching words. Somehow I got some traffic from Hungary or Ukraine. (I guess form the US are not non-Japanese speaker...)
So I believe it's good to write in English, very sometimes, even once in a blue moon. Sorry, I'm so lazy.
(If somebody eagerly requests me to write in English, I might do it.)

I've just found a fatal bug on my Sagittarius Scheme. How fatal? I need to say VERY!
Here you can see how serious it is.
(define (map) #f)
(display 'buzz) ;; -> COMPILE ERROR!
This is because I was too lazy to implement library system properly. In current implementation, each library has a hash table to store its variables or macros. The problem was it shares global location object by identifier name.
What does it mean?
It's really simple, even though it looks it has library system, it shares all variable in global. That's why the above problem was occurred.

The bug was actually found because I was trying to run Gambit's benchmarks. On its benchmarks, there is a function named "reduce". This is the same name as SRFI-1 has and the compiler is using it.
I am re-implementing the library system with hierarchy of libraries so that Sagittarius can separate global location object by library. It's almost done, I just need to re-write compiler a little bit and support rename or prefix stuff.

The most surprising thing was I even didn't notice this bug even though I was using it whole time. (Of course I don't re-implement those basic function for studying. I guess that's why.)

2011-09-06

竹内関数

最近ベンチマークとってないなぁと思って図ってみた。
使用コードは下記。

(import (rnrs))

(define (tak x y z)
  (if (not (< y x))
      y
      (tak (tak (- x 1) y z)
       (tak (- y 1) z x)
       (tak (- z 1) x y))))
(let ((args (command-line)))
  (let ((n (string->number (cadr args))))
    (tak (* n 2) n 0)))

図ったのは以下の3つ。
Sagittarius pre0.1.4
mosh 0.2.6
Ypsilon 0.9.6update3
結果は以下の通り
Sagittarius

real    0m0.725s
user    0m0.702s
sys     0m0.046s

real    0m0.723s
user    0m0.733s
sys     0m0.015s
-------------------
mosh
GC Warning: Repeated allocation of very large block (appr. size 69632):
        May lead to memory leak and poor performance.

real    0m0.794s
user    0m0.780s
sys     0m0.015s
GC Warning: Repeated allocation of very large block (appr. size 69632):
        May lead to memory leak and poor performance.

real    0m0.797s
user    0m0.796s
sys     0m0.015s
-------------------
Ypsilon

real    0m0.931s
user    0m0.015s
sys     0m0.030s

real    0m0.920s
user    0m0.015s
sys     0m0.015s

両方とも超えてる!最近施したインストラクションのチューニングが効いてるのかな。
竹内関数だけしかベンチマークとってないのであんまり参考にはならないけど・・・
まじめにベンチマークとろうかな。

追記:
試しにgambitのベンチマークを走らせて見たら爆死した。遅い上に途中でエラーで落ちよる。
まだまだだね(こしまえ風)

Spring webflowの話

サーバーサイドJavaをやってる人なら避けて通れないSpring framework。その中の一つにwebflowがあるのだが、これではまっている話。

話は実は2つある。

1つ目。
ステートの対するレスポンスの話。
webflowはフローチャートをwebで簡単に実装するためにあるようなもので、状態遷移の管理のフレームワークだと思えばいいはず。っで、はまったのはそれ+Ajaxで起きた。
ある状態からある状態に遷移する際にAjaxを使って一部だけを更新しようとした際に、以下のように書いてはいけない
<view-state id="state1" >
  <transition on="trans1" to="trans2" / >
</view-state>

<action-state id="trans2" >
  <!-- do something -->
  <render fragments="frag1" />
</action-state>
Ajaxを使っている場合は状態遷移を起こすとレスポンスがおかしなことになるっぽい。上記のは単にtransitionタグに入れてやればいいんだけど、似たような処理を一箇所にまとめるということができない。見事にはまった。
正直現状のバージョン(2.2を使用)はAjaxとの相性が悪い気がする。というか、そもそもこれ自体がAjaxを使いことを想定していないような感じ。

2つ目。
現在進行形。
webflowのログの話。
webflowは当然だがログを吐く。もちろんログの制御はlogback.xmlとかその辺のでできる。っが問題があって、どのレベルでも吐いてほしくないログというのはどこにでも存在する。たとえばパスワード。
どの世界にも平文のパスワードを吐き出してほしいと思う開発者はいないはず(まぁ、よからぬことを考えているなら別だが)。
っが、webflow君はあまりそんなこと気にしない。正確にはflowScopeに格納されたプロパティをDEBUGモードだと全部吐き出す素敵仕様。そもそもスコープにパスワードを入れるなということなのかもしれないが・・・

いつまでたってもSpringが好きになれない。すごいフレームワークだとは思うんだけど、なんだかなぁ感がいつまでたっても拭えないからに違いない。

2011-09-04

スペアリブ食べ放題

Grouponで(ずいぶん前に)キューポン買っていたのについに行ってきた。アムステルダムに行くのが今まで億劫だったというのがおもな原因だ。
予約が6時で、5時半にアムスに到着。トラムにのって目的地周辺へ。っで、ここからが問題で、目的地の通りはあるのにその番号がない。どうなってるんだ?と思いながら散策。っが、見つからない。
そうこうする間に6時。しゃーないと思い道を聞きつつ探す。この通りなぜか2本あって、トラムから見える一本目とその裏にもう一本。当然裏の方。見つかるかよ!
店自体は普通のレストラン。アルゼンチン料理のはずだが、なぜかインド人っぽい人が経営。よくある話ではあるが。店員さんは非常にいい人だった。
キューポンにはマグロのステーキ、鮭のステーキ、チキンステーキかスペアリブ2時間食べ放題を選べるとある。ので僕はマグロのステーキで、彼女がスペアリブを注文。1切れもやらんと息巻いていたなぁ・・・
出てきた料理。
マグロのステーキ
付け合せのポテト
本丸スペアリブ
でかかった。マグロもきっと400gくらいはあっただろう。スペアリブが3つって。
えぇ、2つほど僕が食べましたよ。何時の間にやら皿に乗ってるんだもん!!
結局食べ放題なのにお代わりせずでした。
どうでもいいが、えらい痩せてる黒人の女の子(高校生くらいに見えた)が普通に4つめを頼んでいたのにびっくりした。あの体のどこに入るんだろう?

2011-09-02

bloggerのインターフェースが変わった

別にだからどうということはないのだが、統計なるものがあってページビューとか訪問元はどことかが見えるようになった。 今までその辺まったく気にしてなかったのだが、月に100を超えるページがあったりして面白い。(世間一般よりははるかに少ないけど) っで、たいていそのページは昔書いたC++のことだったりJavaのことだったり、ajaxのことだったりするわけだ。 中身を読み返してみると、「せっかく検索してたどり着いたのにこんなごみ記事でごめん」と思うくらい自分のチラシの裏だったりするのでちょっと申し訳なく思ってしまう。 最近Springを使っているのでその辺の話も書いていこうかな。使い方ではなく、はまった話が中心になるけど。

TODOリスト

主にSagittariusでやっておきたいなぁと思ったTODOリスト。
  • let-valuesおよびlet*-valuesの組み込み構文化
    • 現状は(rnrs base)でsyntax-rulesによるマクロで定義されてるが、よく考えれば組み込みにできそう。
  • コンパイル時ラムダリフティング
  • srfi-98の対応
    • ぶっちゃけファイル作るだけなんだが、絶賛放置中。
  • Threadの見直し
    • かなり不安定なので。ただ、あんまり使ってないから優先度が低い。
  • 組み込みCharset
    • 現状はsrfi-14を使用。ただ、正規表現の実装で似たようなものがあるので、統合したい。そうするとどうしても組み込みで必要になる。
とりあえずこんなところ。多分まだある。

追記:
let-valuesとlet*-valuesの組み込みシンタックス化完了。思ったとおり簡単だった。