Journal InTime


2001-04-11 (Wed)

_

何か奥歯が痛いような気がするけど、気のせいに違いない。


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を返してないからかなあ。

Tags: ximapd

_ Projects

TracMultipleProjectsを参考に、複数のプロジェクトをApacheの設定は1つにして管理するようにしてみた。 mod_pythonを使わなくてもできたのか、ってmod_rewrite使えばそりゃできるよな。

Tags: その他

_ ruby-profのstack_tが衝突

バグフィックスしてリリースしたとたんに、新たなバグレポートが。 Mac OS 10.3.8のsys/signal.hにも定義されているらしい。

prof.cの中だけならOKかと思ったが、甘かった。

Tags: Ruby

_ pound

mod_rubyスクリプトで、コードは変わってないはずなのに、 なぜかパフォーマンスが40%くらい落ちてしまっていて、 悩んでいたのだが、pound*1を使うように したせいだった。 入れたのすっかり忘れてたよ。

やっぱり静的なコンテンツはポート番号を変えよう。

もちろん、poundが有用なケースはたくさんあると思いますよ、念のため。

Tags: 仕事

*1  HTTPのロードバランサ


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>'
Tags: Ruby