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>'