OSXでビルドするときは、
make mac; make install-mac
って「mac」が要るのね。ちょっとはまるところだった。
更新モードでopenできるのは一人だけなのかな。更新よりも検索に比重があるんだろうなあ。なのでバッチぽいネタを。MapReduceもどきのミニチュアで素振り。インスタンス変数が一つしかないのか。#なんちゃって関数型?
require 'villa' class Sink def initialize(name) @name = name end def writer(&block) open(Villa::OWRITER | Villa::OCREAT, &block) end def reader(&block) open(Villa::OREADER, &block) end def put(key, value) villa.put(key, value, Villa::DDUP) end def each(&block) reader do villa.each(&block) end end def reduce reader do |v| v.curfirst yield(v.curkey, v.curval) end end def next_value(key) return nil unless villa.curnext return nil unless key == villa.curkey villa.curval end def next_key(key) while true return villa.curkey, villa.curval unless key == villa.curkey return nil unless villa.curnext end end private def var_name "#{self.class}:#{self.object_id}" end def open(mode) Villa::new(@name, mode) do |v| v.silent = true Thread.current[var_name] = v yield(v) end ensure Thread.current[var_name] = nil end def villa Thread.current[var_name] end end def main sink = Sink.new('sink.db') sink.writer do |v| v.clear end sink.writer do while s = gets s.chomp.scan(/[A-Za-z]+/) do |w| sink.put(w, '1') end end end result = Sink.new('sink2.db') result.writer do |v| v.clear sink.reduce do |key, value| while key count = value.to_i while value = sink.next_value(key) count += value.to_i end result.put(key, count.to_s) key, value = sink.next_key(key) end end end result.each do |k, v| p [k, v] end end main