Edit History:View

Edit History:View

Content of hira at 2004/04/03 04:24:12 UTC

View diff from current version

Edit this version

Return to the edit history

  平内です。
  
  Java屋でした。Javaの言語以外の部分が好きだった。いい夢見させてもらったなぁ。
  
  - [[hira:作ったモノ]]
  
  * 質問箱 (済み)
  
  ** 健全なマクロ内でのgensym?
  
  gauche.parameterの実装を眺めていたのですが、tmp1aとtmp2aが不思議でなりません。
  展開されたらtmp1a,tmp2aだらけになるように思ってしまいます。
  実際はgensymされたように振る舞っているようなのですが、一般的にそういうものなのでしょうか。
  このワザは使える!と思ったのですが、裏技だったらどうしようと不安になったので質問してみました。
  - hira: これが答えか。またやってもうた。。。以下、R5RSより抜粋。
  <<<
  テンプレートに現れているがパターン変数でも識別子...
  でもない識別子は,リテラル識別子として出力に挿入され
  る。もしリテラル識別子が自由識別子として挿入されるな
  らば,その場合,その識別子の束縛であって,かつ元々の
  syntax-rules のインスタンスが現れている箇所を含んでい
  るようなスコープの束縛が参照される。
  >>>
  ↓ここでlet変数のgensymを説明している。letの変数部分に来てやっとgensymらしい。
  <<<
  もしリテラル識別子が束縛識別子として挿入されるならば,その場合,その識別
  子は,自由識別子の不慮の捕獲を防ぐために実質的に改名される。
  >>>
  
  {{{
  ;;;lib/gauche/parameter.scm
  (define-syntax %parameterize
    (syntax-rules ()
      ((_ (param ...) (val ...) (tmp1 ...) (tmp2 ...) () body)
       (let ((tmp1 val) ... (tmp2 #f) ...)
         (dynamic-wind
          (lambda () (set! tmp2 (param tmp1)) ...)
          (lambda () . body)
          (lambda () (param tmp2) ...))))
      ((_ (param ...) (val ...) (tmp1 ...) (tmp2 ...) ((p v) . more) body)
       (%parameterize (param ... p) (val ... v) (tmp1 ... tmp1a) (tmp2 ... tmp2a) more body))
      ((_ params vals vars other body)
       (syntax-error "malformed binding list for parameterize" other))
      ))
  
  ;;;sample
  (%parameterize () () () () ((a b) (c d)) body)
  ;hira image
  => (%parameterize (a) (b) (tmp1a) (tmp2a) ((c d)) body)
  => (%parameterize (a c) (b d) (tmp1a tmp1a) (tmp2a tmp2a) () body)
  => (let ((tmp1a b) (tmp1a d) (tmp2a #f) (tmp2a #f))
       (dynamic-wind
         (lambda () (set! tmp2a (a tmp1a)) (set! tmp2a (c tmp1a)))
         (lambda () body)
         (lambda () (a tmp2a) (c tmp2a))))
  ;actual? tmp1b, tmp2bのように一意なシンボルになる
  => (%parameterize (a) (b) (tmp1a) (tmp2a) ((c d)) body)
  => (%parameterize (a c) (b d) (tmp1a tmp1b) (tmp2a tmp2b) () body)
  => (let ((tmp1a b) (tmp1b d) (tmp2a #f) (tmp2b #f))
       (dynamic-wind
         (lambda () (set! tmp2a (a tmp1a)) (set! tmp2b (c tmp1b)))
         (lambda () body)
         (lambda () (a tmp2a) (c tmp2b))))
  }}}
  
  
  ** シンボルの束縛値を得るには
  
  そのスコープに束縛されているシンボルの値が欲しいです。
  {{{
  (define a 'A)
  (define b 'B)
  (define (ab sym)
    (let ((a 1) (b 2))
      (symbol-bound sym)))
  (ab 'a) => 1
  (ab 'b) => 2
  }}}
  これを実現するsymbol-boundはどうやれば作れますか?
  evalを使ってもトップレベルの環境しか見れないので、やはり無理なのでしょうか。
  {{{
  (define (eval-ab sym)
    (let ((a 1) (b 2))
      (eval sym (interaction-environment))))
  (eval-ab 'a) => A
  (eval-ab 'b) => B
  }}}
  
  - [[Shiro]]: 無理です。ローカル変数の名前というのは単なる記号で、
  コンパイル時にのみ使われるので、letの中身が実行されるときには
  aやbという「名前」は存在していません(内部的には、「0番目のローカル変数」、
  「1番目のローカル変数」、のようになっています)。
  一応、デバッグ用の情報を探せば見つけられなくはないですが…
  この機能があったとして、どういうふうに使いたいですか?
  - hira (2004/03/26 17:51:23 PST): 何でもキャストできるような関数を生成するマクロを書いているとき、欲しいと思いました。
  *->listという関数の場合、引数の型がstringならstring->listを呼ぶというものです。
  そのときstring->listをchar-listではなくline-listを返すものに一時的に挿げ替えたいと思いました。
  それをローカル変数の隠蔽で実現しようとした、というのが経緯です。
  
  ** applyは遅い?
  
  {{{
  (use gauche.time)
  (use srfi-1)
  
  ;;everyを知らずに作っちゃったmy-every
  ;;悔しいのでgaucheのeveryと競争してみる
  (define my-every
    (case-lambda
      ((pred           ) #t)
      ((pred val . rest) (and (pred val) (apply my-every pred rest)))))
  
  ;;my-everyからcase-lambdaをはずす
  (define (my-every2 pred . args)
    (if (null? args)
      #t
      (and (pred (car args)) (my-every2 pred (cdr args)))))
  
  ;引数をmy-everyに合わせたgaucheのevery(N-ary caseを削除。Fast pathのみ)
  (define (every pred . lis1)
    (or (null-list? lis1)
        (let lp ((head (car lis1))  (tail (cdr lis1)))
          (if (null-list? tail)
            (pred head) ; Last PRED app is tail call.
            (and (pred head) (lp (car tail) (cdr tail)))))))
  
  (define charlist (string->list "
  01234567890123456789012345678901234567890123456789
  01234567890123456789012345678901234567890123456789
  01234567890123456789012345678901234567890123456789
  01234567890123456789012345678901234567890123456789
  01234567890123456789012345678901234567890123456789
  01234567890123456789012345678901234567890123456789
  "))
  (time (apply my-every  char? charlist))
  (time (apply my-every2 char? charlist))
  (time (apply every     char? charlist))
  
  ;;;結果
  gosh> (time (apply my-every  char? charlist))
  ;(time (apply my-every char? charlist))
  ; real   0.063
  ; user   0.063
  ; sys    0.000
  #t
  gosh> (time (apply my-every2 char? charlist))
  ;(time (apply my-every2 char? charlist))
  ; real   0.017
  ; user   0.015
  ; sys    0.000
  #t
  gosh> (time (apply every     char? charlist))
  ;(time (apply every char? charlist))
  ; real   0.000
  ; user   0.000
  ; sys    0.000
  #t
  }}}
  gaucheのevery速いです。
  my-every2は、たまにmy-every並に遅いときがあります。
  gaucheのeveryはつねに0。これは(一般的に?)applyのコストが高いからなのでしょうか?
  
  - [[Shiro]]: applyの実装は処理系によって全然違うと思うので、一つの
  処理系から一般的な傾向は出せないと思います。Gaucheでもかつては
  applyは非常に遅かったのですが、今はそこそこじゃないかなあ。
  プロファイラが無い状況で上記の結果を説明するのは難しいですが、
  不定長引数を取る関数の呼び出しでrest引数がconsされるせいって理由が
  考えられますね。固定長引数、もしくはrest引数に入る引数が無い場合は、
  引数は全てスタックに置かれるので、アロケーションが発生しません。
  例えばmy-every2は、再帰で呼び出される度に一回consが
  入りますが、everyの方はinner loopはconsが入りません。case-lambda
  で作られた関数は全引数が一度リストにされるので、引数の数だけ
  consされます。その後ディスパッチも入りますから、不利ですね。
  - hira (2004/03/25 01:06:05 PST):どうもです。applyのコストは処理系によって違うんですね。最近case-lambda版の書き方が気に入っていたので、ちょっと気になったのでした。実際のところ、現状の速度で全然問題ないです。
  - [[Shiro]]: case-lambdaも理屈の上ではかなりアグレッシブに最適化できると
  思うんで、必要にせまられたら最適化すると思います。
  
  ** eof
  eof-objectを保持していたいのですが、*eof*のような定数ってありませんか?
  今はこんなことをやって取得しているのですが、どうもしっくりきません。
      gosh> (define eof (with-input-from-string "" (lambda () (read))))
      eof
      gosh> (eof-object? eof)
      #t
  eofの取得方法はこれしかないのでしょうか。
  この質問の背景には[http://www.shiro.dreamhost.com/scheme/gauche/man/gauche-refj_102.html#IDX552 port-for-each]などの「入力ポートと関係していないreader」を簡単に作りたい、という要求があります。
  - fuyuki: バリエーションはいくつか考えられますが(see pack.scm)、基本的にそういう手しかないはずです。
  - hira (2004/03/25 00:08:43 PST):どうもです。そうでしたか。Javaの場合EOFは-1だから考える必要なかったんですよね。Gaucheにも定数で欲しいなぁ。
  - fuyuki 2004/03/25 19:38:08 PST: eofが定数になってないのは、あまりそれが一般的な意味でのオブジェクトではないからじゃないかと思います。うまく説明できませんが、Schemeがそうしない理由はなんとなくわかります。Scheme的。が、実用上不便なのはたしかなので、srfiにしてみるといいかもしれません。:)
  - hira (2004/03/26 01:44:29 PST): あとundef。Schemeにはnullが無いんですよね。'()だの#fではなく「型無し値無し」を意味するnullが無い('()はlist、#fはboolean)。undefに巷のnull並の地位を与えてやりたいです。booleanな束縛の初期化に'()、listな束縛の初期化に#fと使い分けるというのも貧乏臭くてイヤだなぁと。
  {{{
  gosh> (define u1 (print))
  
  u1
  gosh> u1
  #<undef>
  gosh> (eq? u1 (newline))
  
  #t
  }}}
  
  ** define-procedure, procedure-rules
  
  下のマクロはプロシージャの方が良いのですが、マクロの引数マッチが便利なのでマクロにしちゃってます。
  {{{
  (define-syntax /fi
    (syntax-rules ()
      ((_ (inf opt)      thnk ) (apply with-input-from-file inf thnk (apply %add-autoditect (%parse-opt opt 'i)) ))
      ((_ (inf args ...) thnk ) (apply with-input-from-file inf thnk (      %add-autoditect  args ...          ) ))
      ((_  inf           thnk ) (      with-input-from-file inf thnk                        :encoding "*JP"      ))
      ))
  }}}
  これを次のようなプロシージャに変換したいのですが、どうするのが手っ取り早いでしょう。
  作ろうかと思ったのですが、有り物があるならそれを使いたいなぁと思いまして。
  {{{
  (define (/fi . args) 引数パターンでディスパッチして、引数をちゃんとバインドする)
  }}}
  
  - [[Shiro]] (2004/03/18 03:02:02 PST): syntax-rulesまで複雑なマッチングは使えませんが、
  複数のlambda listパターンを持たせるならcase-lambdaというのがあります。
  srfi-16ですが、Gaucheでは組み込みになっています。
  - hira (2004/03/18 03:11:35 PST): どもっす。やっぱりありますよね。早速みてみます。
  - hira (2004/03/18 04:42:23 PST): やってみました。1と2は「infがboundされていない」と怒られてしまいますね。これがsyntax-rules未満な部分でしょうか。なんか中途半端だなぁ。でも作るのは凄く大変そう。実装のイメージが全然わきません。
  {{{
  (define /fi
    (case-lambda
  ;1  (((inf opt)      thnk ) (apply with-input-from-file inf thnk (apply %add-autoditect (%parse-opt opt 'i)) ))
  ;2  (((inf args ...) thnk ) (apply with-input-from-file inf thnk (      %add-autoditect  args ...          ) ))
      (( inf           thnk ) (      with-input-from-file inf thnk                        :encoding "*JP"      ))
      ))
  }}}
  
  *** 参考
  
  - [http://srfi.schemers.org/srfi-16/srfi-16.html srfi-16]
  - [http://www.shiro.dreamhost.com/scheme/gauche/man/gauche-refj_20.html#IDX24 Gaucheマニュアル]
  - [http://www.cs.huji.ac.il/support/docs/drscheme/mzscheme/node22.htm PLT]
  
  * hogeとワタシ
  
  - Schemeとワタシ
  -- 2000年頃、Scheme本を読んで「こいつぁ一生つきあえる言語だ!」と確信する。
  -- 実用に足る処理系を探しつつ、Scheme(Lisp)本を買いあさる。
  -- Gaucheを見て「こいつは一生つきあえる処理系かも?」と思う。
  -- ヒマが手に入ったので、一気にSchemeをモノにしようと修行に励んでいる。
  
  - Javaとワタシ
  -- 2番目に読んだ技術書が「Java言語入門 ローラ・リメイ著」(初めて読んだ技術書?は「コの業界のオキテ」)
  -- 初めてプログラマーとして入った会社が、組込JavaOSを作ってるアツい所だった。
  -- Javaには色々文句あるけど、他人にJavaの悪口を言われると、つい凹でしまう。
  
  - プログラミングとワタシ
  -- ゲーム作りたいなー。じゃあ、プログラマーになるか。という訳でなったらしい。
  -- ゲーム製作は人工知能を組むところで挫折。Schemeをモノにしたら再開しよう。
  
  
  
  ----
  
  * hira:log
  
  ** [http://d.hatena.ne.jp/hirau/ Hatena]に引越しました。(2004/03/17 22:30:06 PST)
  
  たまにツッコミ入れてやってください。
  
  ** fio
  
  filter云々の前に、現状のGaucheで何が出来るかイロイロ試している。
  でもI/O周りの関数名やオプション名はめちゃくちゃ長いし、thunkだわprocだわlambdaだらけで、もうイヤ、て感じ。
  試しに、名前を短くしてthunk,procをマクロ化してみた。
  
      gosh> (use hira.fio) => (#<module hira.fio> #<module gauche.interactive>)
      gosh> (fo "t1" (ds :< :hello 1 :> )) => #<undef>
      gosh> (fo "t2" (wr :< :hello 2 :> )) => #<undef>
      gosh> (fo "t3" (fm "<[~10a][~10a] ~d>" (so (fi "t1")) (so (fi "t2")) 3 )) => #<undef>
      gosh> (fo "t4" (pr "<" (so (fi "t1") (fi "t2") (fi "t3") (si "world")) " "  4 "> ")) => #<undef>
      gosh> (fio "t4"  "t5") => 58
      gosh> (define t5 (so (fi "t5"))) => t5
      gosh> t5 => "<<hello1>:<:hello2:><[<hello1>  ][:<:hello2:>] 3>world 4>\n"
  
  非常に快適だ。デフォルトのexprをcopy-portにしてから面白くなってきた。(2004/03/17 09:25:11 PST)
  
  ** マクロ固め
  
  昨日はthunkを撲滅しようと思ったのだが、ちと浅はかだった気がしてきた。
  gauche.testのtest*なんかは一気に書き下すとき便利だけど、thunkを変数として扱えるtestのほうが柔軟性はある。
  test*だけではつらいかも。昨日つくったfi,fo,fio,si,so,sioにはそれぞれ*付き版を用意すべきか。。。
  ・・・いや違う。そのときはオリジナルを使えばいいのだ。書き捨て・即効性重視のマクロだ。柔軟性は捨てよう。(2004/03/16 07:52:25 PST)
  
  ** ノーサンクス
  
  今日はthunkでハマった。
  
      (with-input-from-file "1.tsv"
        (port-for-each (lambda (l) (print ">" l)) read))
  
  これだとウンともスンとも言わずに固まってしまう。
  標準入力が1.tsvに切り替わっておらず、コンソール入力でブロックしているのが原因。
  こうするのが正しい。
  
      (with-input-from-file "1.tsv"
        (lambda ()
          (port-for-each (lambda (l) (print ">" l)) read)))
  
  with系ioでlambdaを忘れる、の巻でした。
  悔しいのでこんな風に書けるマクロを作った。
  
      ;;上の例と同じ
      (fi "1.tsv" (port-for-each (lambda (l) (print ">" l)) read))
      ;;1.tsvから読み込んで2.tsv(:if-exists :append :buffer :line :if-does-not-exist :error)に書き込む
      (fio "1.tsv" ("2.tsv" :xablne) (port-for-each (lambda (l) (print ">" l)) read))
  
  こういうのが「言語以上・ライブラリ未満」ていう領域なんだろうな。
  fi,fo,fio,si,so,sioと作りながら「Schemeの名前、長すぎだよー」と改めて思う。
  名前を短く、thunkを撲滅したくなった一日だった。
  (2004/03/15 07:12:03 PST)
  
  ** Schemeを256倍使うための本
  
  そんな本が読みたいなぁ。あと、イディオムを沢山紹介してくれる本かな。Schemeは言語以上ライブラリ未満な領域が広いし、
  「やり方は何通りもある」の権化だから、似たような表現をイロイロ比較検討できるのがいいな。
  ちなみに[http://mitpress.mit.edu/sicp/ 「Schemeを16777216倍使うための本」]は凄過ぎなので却下。65536倍薄めてくれないと読めません。(←そもそもScheme本じゃないか、これは)。(2004/03/14 11:38:27 PST)
  
  -- あぁ欲しいですね。
  でもイディオムってよりやっぱマクロ中心希望!~%
  そうすれば''「schemeを256倍拡張する本」''でなんとなくうれしい。~%
  いや、(define 本 (lambda () (拡張する schemeを 256倍)))かな。[[cut-sea]]:2004/03/23 00:10:35 PST
  
  ** 好きなもの
  
  - 星新一
  - RAMONES
  - vi
  - Unixのツール
  - Scheme
  
  シンプルで、速くて、楽しいものが好きなのだ。
  どれもクローンされまくりだってのがミソ。(2004/03/13 08:43:15 PST)
  
  
  ** 続・夕日のプログラマー
  
  [http://www.namazu.org/%7Esatoru/misc/bad-knowhow.html バッドノウハウと「奥が深い症候群」]が面白い。
  [http://www.hyuki.com/techinfo/knowhow.html バッドノウハウからグッドラッパーへ]なんてのもあるし。
  
      良いものに対するノウハウはグッドノウハウ。
      悪いものに対するノウハウはバッドノウハウ。
      良いものに対するラッパーはグッドラッパー。  (バッドラッパー?)
      悪いものに対するラッパーはバッドラッパー。  (グッドラッパー?)
  
  なんて言い方したら議論にならんな。ラッパーはラッピーを否定する意味で使うべきなのか?
  
      醜いものに対するノウハウはアグリーノウハウ。
      醜いものに対するラッパーはアグリーラッパー。  (ビューティフルラッパー?)
  
  いかんな、これじゃ。だから何よって感じがする。
  
      バッド = ダメな仕様に対するワークアラウンド => ノウハウ
      グッド = ダメな仕様に対するワークアラウンドに対するワークアラウンド => ラッパー
  
  てこと?じゃあ
  
      アグリー = ダメな仕様 => プログラム
  
  だな。'''「The Wrapper, The Knowhow, And The Program」'''でどうでしょ?いや、タイトルの話(←なんのタイトルじゃ!)。(2004/03/12 08:34:10 PST)
  
  ** ((癒し系))
  
  最近Cをいじってるけど、どうも落ち着かない。心許無い感じがする。丸裸で肌寒い感じ。~%
  ・・・たぶん、(温もり)が恋しいんだろう。(2004/03/11 06:51:51 PST)
  
  ** 時間合わせ
  
  WiLiKiはPSTだし、ShiroさんからのメールはHSTだ。
  それがどうもピンとこない。
  {{{
      JST 日本   :       0       : 24 - 5 = 19 : 24 - 7 = 17
      HST ハワイ : -24 + 5 = -19 :      0      :  0 - 2 = -2
      PST 太平洋 : -24 + 7 = -17 :  0 + 2 =  2 :      0
  }}}
  よし。これなら理解できる。GMT-8よりJST-24+5の方が実感わくなぁ。(2004/03/10 08:03:04 PST)
  
  ** マクロデビュー
  
  今までlambdaで実現できるようなマクロばかりを書いていた。
  でも、こいつぁマクロでなきゃいかん。
  {{{
  (define-syntax inc! (syntax-rules () ((_ slot) (set! slot (+ slot 1)))))
  (define-syntax dec! (syntax-rules () ((_ slot) (set! slot (- slot 1)))))
  }}}
  これでやっとマクロの必要性を実感する事ができた。
  なーんだ、ただのマクロじゃん(←だからそうだって)ていう感じ。(2004/03/09 07:02:06 PST)
  - hira:これ、Gaucheにもっとすごいのがついてた。[http://www.shiro.dreamhost.com/scheme/gauche/man/gauche-refj_21.html#SEC23 マニュアル 4.4 代入](2004/03/15 15:12:26 PST)
  
  ** セロ弾きのゴーシュ
  
  {{{
   「森で生きている間、私は黙っていた。
    命を失った今、澄んだ声で歌う。」
                 古いチェロにかかれていた言葉
  }}}
  Gaucheの名前の由来は絶対これだと予想している私。
  上の引用は[http://www.cello.jp/cellist ココ]で発見。
  そういやλもlambdaになってからの方が、活き活きしてるような。(2004/03/08 10:57:47 PST)
  - それもありそうですが、私はむしろ
  Gauche->左->ぎっちょ->*ぶきっちょ->AWKward
  な流れのほうが濃いのではないかと踏んでいます(まあ詰めてしまえばどっちでも同じようなものですが)。
  なお、*のあたりは私の見解を反映したものではありません。:) --fuyuki
  - うへー。[http://www2.alc.co.jp/ejr/index.php?word_in=gauche&word_in2=%82%A0%82%A2%82%A4%82%A6%82%A8&word_in3=PVawEWi72JXCKoa0Je Gauche]って形容詞だったんすね。JohnnyとかJoeyとか、人名にしか使われない単語だと思ってました。「セロ弾きのぶきっちょ」か。おお、なるほど。[[hira]](2004/03/09 20:07:04 PST)
  
  ** ビックリ事件
  
  2,3日前、sort!の「破壊的に再利用」の意味を誤解してハマったことがあった。
  MLを読み返していたら[http://lists.sourceforge.jp/mailman/archives/gauche-devel-jp/2003-January/000077.html 似たような話]が出てきたのでsort!だけじゃ無いのかとビックリした。
  しかし、どうにも分かりにくい。なんでだろ。
  {{{
  1. 元の値も戻り値も使用したい。(副作用なし)
  2. 元の値を使用したい。(set!しなおす手間を省きたい。メモリを節約したい)
  3. 戻り値を使用したい。(メモリを節約したい)
  }}}
  1と2の感覚しか持ち合わせていなかった、ということか。
  2は束縛への副作用を目的としているのだけど、3では束縛への副作用は効率化のための手段に過ぎない。
  副作用の有無だけでなく、2と3の違いが見た目で分かるようにならないかなぁ。3は「!!」にするとか。
  sort, sort!!, remove, remove!!となっていればこんなハマり方しなくて済むのだけれど。。。(2004/03/07 06:32:50 PST)
  - [[hira]]:これはリストならではの問題か。vectorに「!!」はありえないんだよなぁ。コレクションとしてlistとvectorを同一視出来ないってのは、やっぱりビックリだ。と思ったら、gauche.collection には「!」系が無かった。・・・この辺はあとで整理しておこう。R5RS,SRFI,gauche.collectionとRuby,Javaなどのコレクションとの比較だな。(2004/03/07 17:40:28 PST)
  
  - [[Shiro]]: まとめましょう→[[Scheme:!と?]]
  
  ** 思い込んだら、試練の道
  
  久しぶりに「switch文のbreak忘れバグ」にハマった。これとtypoは私の天敵だ。簡単に半日は持っていかれる。
  自分は正しい、と思い込んでるため、疑惑があさっての方向に向かってしまうからだ。
  困難なバグの場合、それに喰らいついて解決したら「俺ってすごいぜ!」と満足感が味わえるものだが、
  typoを半日かけて解決した日にゃ「俺ってアホだぜ。。。」とがっかりするしかない。
  ま、年に一度のイベントだと思えばいいか。今年はもう無いだろう。(2004/03/06 17:30:21 PST)
  
  ** 論よりRun
  
  今日はportapi.cの宿題を片付けようと、一日中Makefileをイジクリまわしていた。
  結局./libgauche_*.dllを最適化戦略の数だけ作り、./gosh -ftest io_bench.scmする前に./libgauche.dllにmvすることにした。
  {{{
     text    data     bss     dec     hex filename
   463508   62132   37584  563224   89818 libgauche_0.dll
   464052   62132   37584  563768   89a38 libgauche_0i.dll
   474132   62132   37584  573848   8c198 libgauche_org.dll
  -------------------------------------------------------------------------------
  arc         i686-pc-cygwin
  thread-type none
  
  strategy real    user    system  process
  0        35.01   12.99   19.46   32.46    #全体をSAFE_CALLで囲む
  0i       41.37   12.54   25.73   38.27    #全体をSAFE_CALLで囲む(インライン展開)
  org      34.20   11.84   19.61   31.45    #オリジナル
  }}}
  インライン展開がこんなに遅いとは。。。なんでやろ?(2004/03/05 07:24:27 PST)
  
  ** 何も出力しないマクロが欲しい
  
  気兼ねなくデバッグログを埋め込みたいので、何も出力しないマクロが欲しい。
  
  {{{
  (define-syntax p (syntax-rules () ((_ msg ...) (print "***p***>" msg ... ))))
  (define-syntax p (syntax-rules () ((_ msg ...)    ))) ;コレがやりたいんだけどsyntax errorになる
  (define-syntax p (syntax-rules () ((_ msg ...) () ))) ;仕方ないからコレでガマン
  
  (begin (p 'a)(p 'a)(p 'a)(p 'a)) ;(1)
  (begin)                          ;(2)
  }}}
  
  (1)と(2)が同じ意味になるようなマクロって定義できないのだろうか。(2004/03/04 06:17:31 PST)
  
  - [[Shiro]] (2004/03/04 07:04:42 PST): R5RS的には(begin)は未定義で、
  Gaucheの現在のふるまいも「たまたまそう動いている」というものにすぎません。
  ただ、もし余分な () がシーケンスの途中に入ることによる性能低下を
  気にしているのでしたら心配御無用、値が使われないリテラルは
  コンパイル時に消えます。(tail positionにあったら消えませんが、
  その場合はデバッグマクロの有り無しで戻り値が違ってしまいますね)。
  - [[hira]] (2004/03/04 14:01:57 PST): おお、それなら性能低下を気にせずにすみますね。
  ちなみにtail positionではこんなの使ってます。
  {{{
  (define-syntax pp
    (syntax-rules ()
      ((_ val msg ...)
        (let1 result val
          (print "***pp**>" msg ... " :val<" result ">")
          result))))
  }}}
  性能が低下するなら、ppしか使えないなぁと心配してたんですが、取り越し苦労でした。
  - [[Shiro]]: valが多値になる場合に御注意。
  
  ** coroutine = subroutineだと思ってたあの頃
  
  coroutineて書き言葉を見るまで、自分の勘違いに気付かなかった。
  Kahuaセミナー聞いてた時もこんなだったし↓
  
  {{{
  
      「コルーチン」などはcall/ccの例として、ほげほげふがふがどうのこうの・・・
      「子ルーチン」
      「サブルーチン」
      (゚Д゚)ハァ? oO(call/ccって謎だなー)
  
  }}}
  
  過去にどれだけ「コルーチン」という言葉を見聞きしたか、記憶をたぐるのが恐ろしい。
  (2004/03/03 07:37:21 PST)
  
  ** クラスの中に入りたい
  
  slotにprivateなアクセッサを定義しようとして、あれ?っと思いました。
  generic functionでディスパッチということは、自他の区別なんて無いのかと。
  moduleのimport/exportが近いけど、staticな変数の可視/不可視の制御なので、ちょっと違う。
  slotにpublic/privateの概念を持ち込むにはどうすればいいのだろう?
  クラスの中に入る仕組みがあれば良いのだろうけど。
  そうすれば、slot-refにイライラしなくても済むっていうオマケも付くのだが。
  (2004/03/02 07:42:32 PST)
  
  {{{
  (slot-ref self 'hoge) ;;21文字 CLOS:フツーの書き方
  this.getHoge()        //14文字 Java:thisマニアが自己カプセル化したときの書き方
  hoge                  ;; 4文字 CLOS/Java:私が望む書き方
  }}}
  
  - [[Shiro]]: これは興味深いテーマなので、移動しましょう→ [[Gauche:スロットアクセス]]
  
  * portapi実験場
  
  ML:[http://lists.sourceforge.jp/mailman/archives/gauche-devel-jp/2004-February/000648.html 予定とベンチ]
  Rev.30:[http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?p=hira&c=hv&t=1078713876 まとめる前のportapi実験場]
  
  ** 「2. 全面的にScm_MakeVirtualPortを採用してみる」版の設計
  
  - hira: p->Getbのような直呼び出しを狙ったのだけれど、ポート生成のタイミングや参照のされかたが思ったよりも複雑そうでリファクタリングパスが定まらず、挫折。(2004/03/13 17:37:27 PST)
  
  ※FdはFile, Socket, Stdin/out/errの親クラスという位置づけ。
  {{{
  struct ScmPortRec {
      /* 省略 */
      union {
          /* 省略 */
          //これは廃止して以下に展開する
          //ScmPortVTable vt;       /* virtual port */
      } src;
  
      /* portapi interface. */
      /* safe */
      int       (*Getb)(ScmPort *p);
      int       (*Getc)(ScmPort *p);
      int       (*Getz)(char *buf, int buflen, ScmPort *p);
      ScmObj    (*Getline)(ScmPort *p);
      int       (*ByteReady)(ScmPort *p);
      int       (*CharReady)(ScmPort *p);
      void      (*Putb)(ScmByte b, ScmPort *p);
      void      (*Putc)(ScmChar c, ScmPort *p);
      void      (*Putz)(const char *buf, int len, ScmPort *p);
      void      (*Puts)(ScmString *s, ScmPort *p);
      void      (*Flush)(ScmPort *p);
      ScmObj    (*Close)(ScmPort *p);
      ScmObj    (*Seek)(ScmPort *p, ScmObj off, int whence);
      /* unsafe */
      int       (*GetbUnsafe)(ScmPort *p);
      int       (*GetcUnsafe)(ScmPort *p);
      int       (*GetzUnsafe)(char *buf, int buflen, ScmPort *p);
      ScmObj    (*GetlineUnsafe)(ScmPort *p);
      int       (*ByteReadyUnsafe)(ScmPort *p);
      int       (*CharReadyUnsafe)(ScmPort *p);
      void      (*PutbUnsafe)(ScmByte b, ScmPort *p);
      void      (*PutcUnsafe)(ScmChar c, ScmPort *p);
      void      (*PutzUnsafe)(const char *buf, int len, ScmPort *p);
      void      (*PutsUnsafe)(ScmString *s, ScmPort *p);
      void      (*FlushUnsafe)(ScmPort *p);
      ScmObj    (*CloseUnsafe)(ScmPort *p);
      ScmObj    (*SeekUnsafe)(ScmPort *p, ScmObj off, int whence);
  };
  
  /* portapi implements */
  /*Scm_<TYPE><METHOD><UNSAFE>*/
  /*Getb*/      Scm_FdGetb Scm_IStrGetb
  /*Getc*/      Scm_FdGetc Scm_IStrGetc
  /*Getz*/      Scm_FdGetz Scm_IStrGetz
  /*Getline*/   Scm_FdGetline Scm_IStrGetline
  /*CharReady*/ Scm_FdCharReady Scm_IStrCharReady
  /*ByteReady*/ Scm_FdByteReady Scm_IStrByteReady
  /*Putb*/      Scm_FdPutb Scm_OStrPutb
  /*Putc*/      Scm_FdPutc Scm_OStrPutc
  /*Putz*/      Scm_FdPutz Scm_OStrPutz
  /*Flush*/     Scm_FdFlush
  /*Close*/     Scm_FdClose
  /*Seek*/      Scm_FileSeek Scm_IStrSeek Scm_OStrSeek
  
  /*あとFdのUnsafe系とnull系(すでにある)*/
  }}}
  
  interfaceとimplementsのバインドはポート生成時に行う。
  
  狙いは保守・拡張しやすいソース
  - Gaucheは文字列ポートにかなり依存しているので、文字列ポートの
  作成と読み書きは軽くなければならない。
  - Fd系に関しては速度5%落ちだけど、その他のおまけが色々付いてくる、という線。
  文字列ポートは現状維持を目指す。
  
  ** 最新ベンチ結果
  
  {{{
  #sigprocmaskを呼ぶ版
     text    data     bss     dec     hex filename
   462804   62196   37584  562584   89598 libgauche_0.dll
   463668   62196   37584  563448   898f8 libgauche_0i.dll
   468308   62196   37584  568088   8ab18 libgauche_1.dll
   473908   62196   37584  573688   8c0f8 libgauche_1i.dll
   474292   62196   37584  574072   8c278 libgauche_org.dll
  -------------------------------------------------------------------------------
  arc         i686-pc-cygwin
  thread-type none
  
  strategy real    user    system  process
  0        21.95   11.17   9.532   20.70    #全体をSAFE_CALLで囲む
  0i       22.87   11.92   9.498   21.42    #全体をSAFE_CALLで囲む(インライン展開)
  1        21.75   10.67   9.222   19.89    #SAFE_CALLの前にportタイプで分岐する
  1i       21.50   10.21   9.5     19.71    #SAFE_CALLの前にportタイプで分岐する(インライン展開)
  org      20.59   9.972   9.562   19.53    #オリジナル
  }}}
  
  ** sigprocmaskを呼ばないようにしてみる
  
  ML:[http://lists.sourceforge.jp/mailman/archives/gauche-devel-jp/2004-March/000670.html sigsetjmp on port locking]
  
  - [[Shiro]]: CVS版はポートロックの度にsigprocmaskを呼ばないように
  なっています。結構差が出るみたいなんで、それを加味して試してみて
  下さい。src/gauche/vm.hだけ直しても差が出るかも。
  - [[hira]]: やっぱりsigprocmaskは必要っぽいです。
  make testしたときに、systemのテストから返ってこなくなっちゃいました。
  {{{
  Testing system ...
  }}}
  Cygwinの場合、下のようなエラーが出るはずなんですが。
  {{{
  Testing system ...                                               failed.
  discrepancies found.  Errors are:
  test normalize: expects "/cygdrive/d/home/abc" => got "/cygdrive/d/home/win/abc"
  
  test sigalrm1: expects 14 => got 0
  }}}
  - [[Shiro]]: どこで止まったかわかります? (test.logの最後を見てください)。(2004/03/06 18:26:41 PST)
  - [[hira]]: ココで止まってました。
  {{{
  test fork & sigint, expects #t ==> 
  }}}