遅延評価
世の中遅延評価が流行っているみたいです。
僕も抽象構文木を作って遅延評価する逆ポーランド電卓を作ってみました。値が再利用されないので、ぜんぜん面白くありません。いまいち。やっぱり関数定義くらいはできないとなぁ。
class Node def initialize(name, func, *args) @name, @func, @args = name, func, args @value = @func ? nil : args.first end def evaluate unless @value puts "evaludate >>> #{self.inspect}" @value = @func[*@args] @func = nil @args = nil puts "evaludate <<< #{self.inspect}" end @value end def inspect if @value @value.inspect else "(#{([@name] + @args).map {|arg| arg.inspect }.join(', ')})" end end end def rpcalc(s) tree = [] s.split(/\s+/).each do |token| tree = case token when '+' [Node.new(:+, lambda {|a, b| a.evaluate + b.evaluate}, *tree)] when '-' [Node.new(:-, lambda {|a, b| a.evaluate - b.evaluate}, *tree)] when '*' [Node.new(:*, lambda {|a, b| a.evaluate * b.evaluate}, *tree)] when '/' [Node.new(:/, lambda {|a, b| a.evaluate / b.evaluate}, *tree)] else tree + [Node.new(nil, nil, token.to_i)] end end tree.first.evaluate end p rpcalc('1 2 + 4 * 2 /') # => evaludate >>> (:/, (:*, (:+, 1, 2), 4), 2) # evaludate >>> (:*, (:+, 1, 2), 4) # evaludate >>> (:+, 1, 2) # evaludate <<< 3 # evaludate <<< 12 # evaludate <<< 6 # 6