2005-04-11 (Mon)
_ Becky!対応
FETCHが実装されるとBecky!で読めるかな〜と思ったが、相変わらず一覧が出ない。エラーはEXPUNGEでしか出てないんだが。何がいけないんだろう。つーか、未読が2000件とか出てる時点でなんか変(笑)。またメールボックス作り直してみるか?
Thunderbirdでの動作はだいぶ良好で、UNSEEN実装のおかげでMLの未読が出るようになった! 便利! でもなぜか、こっちもINBOXの一覧が出なくなっちゃった!(こっちはINBOXだけ) なんでや……orz。
[ただのにっき(2005-04-11)より引用]
うーん、何ででしょうね。 Becky!はSEARCHで未取得メールをチェックするようなのでSEARCHの結果がおかしいとか。 ximapd.rb -dのログをいただければ何かわかるかもしれません。 EXPUNGEはとりあえずNOOPとして実装しました(そんなんばっかり)。
あと、自分のThunderbirdではINBOXの一覧はちゃんと出ますね。 INBOXの未読管理は何かおかしいんですけど、SELECTのuntagged responseでUNSEENを返してないからかなあ。
_ Projects
TracMultipleProjectsを参考に、複数のプロジェクトをApacheの設定は1つにして管理するようにしてみた。 mod_pythonを使わなくてもできたのか、ってmod_rewrite使えばそりゃできるよな。
_ ruby-profのstack_tが衝突
バグフィックスしてリリースしたとたんに、新たなバグレポートが。 Mac OS 10.3.8のsys/signal.hにも定義されているらしい。
prof.cの中だけならOKかと思ったが、甘かった。
2012-04-11 (Wed)
_ Rubyで遅延評価 - delay, force, lazy
正格評価の言語で明示的に遅延評価を行う方法として、Schemeのdelay/forceがある。 Rubyで実装するとこんな感じ。
class Promise NULL = Object.new def initialize(&block) @value = NULL @block = block end def self.delay(&block) new(&block) end def force if @value == NULL @value = @block.call else @value end end end count = 0 x = Promise.delay { count += 1; 1 + 2 } p x.force #=> 3 p x.force #=> 3 p count #=> 1
メモ化してくれるので、delayされた式は何回forceしても一度しか実行されないのがポイント。
しかし、この実装には問題があって、末尾呼び出しの最適化を有効にしても以下のコードがstack overflowになってしまう。
def loop Promise.delay { loop.force } end loop.force
この例だとエラーになっても害がないと思われるかもしれないが、遅延評価の言語で末尾再帰になるような関数をdelay/forceで書こうとすると、上記のようにPromise.delay { (...).force }という形が出て来るのでちと困る。
そこで、SchemeのSRFI-45でlazyという機能が導入されており、(delay (force ...))の代りに(lazy ...)とすることで解決できる。
Rubyでの実装は以下。
class Promise Box = Struct.new(:type, :value) def initialize(type, value) @box = Box.new(type, value) end private_class_method :new def self.lazy(&block) new(:lazy, block) end def self.eager(value) new(:eager, value) end def self.delay lazy { eager(yield) } end def force content = box case content.type when :eager content.value when :lazy promise = content.value.call content = box if content.type != :eager content.type = promise.box.type content.value = promise.box.value promise.box = content end force else raise ScriptError, "should not reach here" end end protected attr_accessor :box end $c = 0 def loop $c += 1 Promise.lazy { loop } end at_exit { p $c } loop.force
末尾呼び出しの最適化を有効にして実行すると、ちゃんと無限ループになる。 Ctrl+Cで止めると以下のように実行回数が表示される。
$ ruby-trunk -e 'RubyVM::InstructionSequence.compile_option = \ {:tailcall_optimization => true, :trace_instruction => false}' \ -e 'load(ARGV[0])' t.rb ^C133411 t.rb:34:in `force': Interrupt from -e:3:in `load' from -e:3:in `<main>'