著作一覧 |
.... Finished in 164.096424 seconds. 1) Failure: test_verify(OpenSSL::TestX509Store) [./openssl/test_x509store.rb:163]: <true> expected but was <false>. 970 tests, 10357 assertions, 1 failures, 0 errors ~/devl/ruby-1.8.2/test$ ruby -v ruby 1.8.2 (2004-12-25) [powerpc-darwin7.7.0]
opensslがなんであるか知る気も起こさないようにしてきたけどそろそろ知るべき時が来たような気がする。
#とりあえず、Macでrjb-0.1.7のtest.rbは通るな。
言語に対して、文法表現と、それを利用して文を解釈するインタプリタを一緒に定義する
確かになんだかわからん。
ミソは終端表現と非終端表現を一緒に扱えるようにするという点なのかな。
という記事を思い出したので調査。というか、インタープリタは結構使うからだが(エンジンを借りる場合もあればでっち上げる場合もある)。
Four patterns were voted off. Factory Method (due to the confusion over what it means - the pattern is different to the more common usage of the term), Bridge, Flyweight, and Interpreter.
この議論はどういう観点からなんだろうか(ファクトリメソッドパターンは名前が悪いという理由が書かれているが)? すでに言語あるいはミドルウェアで標準的に提供されている/考慮不要化されているために、デザインパターンとしての存在意義を失ったということなのかな?
Javaでフライウェイトを利用するのは参照されているかどうかを判断できないのですごく難しいが、そういう意味なのかな?
例)たくさんのレコードの繰り返しにフライウェイトを使いたい場合
RecordObject flyweight = null; while (resultSet.next()) { // 例えばCOMであれば、 // if (flyweight == null) { // flyweight = new RecordObject(); // } // if (flyweight.refCount() > 1) { // flyweight = new RecordObject(); // しょうがないな // } // と参照カウンタが1(生成時のデフォルト)であればそのまま同じインスタンスを利用できる flyweight = new RecordObject(); // フライウェイトじゃないじゃん // Javaだとconsumerが(たとえばCollectionに入れるなどで)参照を保持したかどうかは判断できないので常に作り直しが必要となる。 // これを防ぐにはResultSetやRowSetのように同一インスタンス内に次のレコードの内容をフィルする方法を取る必要がある。 flyweight.fill(resultSet); consumer.nextRecord(flyweight); }
デザインパターンのインタープリタパターンってこんな感じになるのかな(と、出先なものでGoFに当たれないのがなんとも。というか自分のためのメモですね)。
=begin 以下のプログラムのインタープリタを仮定する。 a = 0 loop: a = a + 1 if a < 5 goto loop end puts a =end class Var def initialize(name) @name = name end def interpret(c) c[@name] end attr_reader :name end class Let def initialize(lval, rval) @lval = lval @rval = rval end def interpret(c) c[@lval.name] = @rval.interpret(c) end end class Add def initialize(lval, rval) @lval = lval #これ名前が悪いな @rval = rval end def interpret(c) @lval.interpret(c) + @rval.interpret(c) end end class Lt def initialize(lval, rval) @lval = lval #同じく悪い名前 @rval = rval end def interpret(c) @lval.interpret(c) < @rval.interpret(c) end end class Num def initialize(val) @value = val end def interpret(c) @value end end class Label def initialize(name, index) @name = name @index = index end def interpret(c) nil end attr_reader :index, :name end class If def initialize(cond, clause) @cond = cond @clause = clause end def interpret(c) if @cond.interpret(c) @clause.interpret(c) end end end class Goto def initialize(label) @label = label end def interpret(c) c.next = @label.index end end class Puts def initialize(var) @var = var end def interpret(c) puts @var.interpret(c) end end class Context def initialize() @pgm = [] @var = {} @next = 0 end def interpret() while @next < @pgm.size n = @next @next += 1 @pgm[n].interpret(self) end end def add(nd) @pgm << nd end def []=(n, v) @var[n] = v end def [](n) @var[n] end def current @pgm.size end def label(name) @pgm.each do |x| return x if Label === x and x.name == name end nil end attr_accessor :next end c = Context.new() c.add(Let.new(Var.new('a'), Num.new(0))) c.add(Label.new('loop', c.current)) c.add(Let.new(Var.new('a'), Add.new(Var.new('a'), Num.new(1)))) c.add(If.new(Lt.new(Var.new('a'), Num.new(5)), Goto.new(c.label('loop')))) c.add(Puts.new(Var.new('a'))) c.interpret
ジェズイットを見習え |