2014-02-11 39 views
1

我正在嘗試做this lesson,我明顯錯過了一些顯而易見的東西! Testfirst.org - rpn_calculator - 如何在方法之間傳遞變量?

require "rpn_calculator" 

describe RPNCalculator do 

    attr_accessor :calculator 

    before do 
    @calculator = RPNCalculator.new 
    end 

    it "adds two numbers" do 
    calculator.push(2) 
    calculator.push(3) 
    calculator.plus 
    calculator.value.should == 5 
    end 

    ... 

    # extra credit 
    it "evaluates a string" do 
    calculator.evaluate("1 2 3 * +").should == 
     ((2 * 3) + 1) 

    ... 

    end 

end

一切工作,以我的眼睛新手除了@numbers。在評估方法中設置@numbers不會影響其他方法中的@numbers,我真的不明白爲什麼。我嘗試了所有我可以谷歌包括更改@數字@@數字,但似乎沒有任何幫助。我只能評估評估方法中的字符串......但我已經有了一個很好的加法,可以使用!

class RPNCalculator 
    attr_accessor :numbers 

    def initialize 
    @numbers = [] 
    end 

    def push(n) 
    @numbers.push(n) 
    end 

    def plus 
    @numbers.length > 1 ? @numbers.push(@numbers.pop(2).reduce(:+)) : fail 
    end 

    def minus 
    @numbers.length > 1 ? @numbers.push(@numbers.pop(2).reduce(:-)) : fail 
    end 

    def divide 
    @numbers.length > 1 ? @numbers.push(@numbers.pop(2).inject{|x,y| x.to_f/y}) : fail 
    end 

    def times 
    @numbers.length > 1 ? @numbers.push(@numbers.pop(2).reduce(:*)) : fail 
    end 

    def value 
    @value = @numbers[-1] 
    end 

    def tokens(pol) 
    pol.split(' ').map{|n| n.to_i.to_s == n ? n.to_i : n.to_sym} 
    end 

    def evaluate(pol) 
    order = [] 
    opps = {:+ => plus, :- => minus, :/ => divide, :* => times } 
    tokens(pol).reverse.chunk{|n| n.is_a?(Integer)}.each{|e,a| e == true ? a.reverse.each{|a| push(a) } : a.each {|a| order.push(a) }} 
    order.reverse.each {|o| (opps[o]) } 
    end 

    def fail 
    begin 
     raise Exception.new("calculator is empty") 
    end 
    end 

end

結果是加回報失敗,因爲@numbers是空的....

RPNCalculator 
    adds two numbers 
    adds three numbers 
    subtracts the second number from the first number 
    adds and subtracts 
    multiplies and divides 
    resolves operator precedence unambiguously 
    fails informatively when there's not enough values stacked away 
    tokenizes a string 
    evaluates a string (FAILED - 1) 

Failures: 

    1) RPNCalculator evaluates a string 
    Failure/Error: calculator.evaluate("1 2 3 * +").should == 
    Exception: 
     calculator is empty 
    # ./12_rpn_calculator/rpn_calculator.rb:59:in `fail' 
    # ./12_rpn_calculator/rpn_calculator.rb:14:in `plus' 
    # ./12_rpn_calculator/rpn_calculator.rb:39:in `evaluate' 
    # ./12_rpn_calculator/rpn_calculator_spec.rb:134:in `block (2 levels) in '

感謝Frank Schmitt我得到它的工作。顯然,人們不會簡單地將方法存儲在哈希中。

正確的評估方法:

 
    def evaluate(pol) 
    @numbers = [] # because this does 4 tests without clearing @numbers 
    opps = {:+ => Proc.new {plus}, :- => Proc.new{minus}, :/ => Proc.new{divide}, :* => Proc.new{times} } # method in proc, thank you Frank :D 
    tokens(pol).chunk{|n| n.is_a?(Integer)}.each{|e,a| e == true ? a.each{|a| push(a) } : a.each {|o| (opps[o].call) }} 
    @numbers[0] 
    end 

回答

0

顯然,紅寶石只要您將它們保存您的有機磷農藥的散列內調用的方法。爲了解決這個問題,你可以使用你的代碼的這個修改版:哎呀哈希裏面

def evaluate(pol) 
    order = [] 
    opps = {:+ => Proc.new {plus}, :- => Proc.new{minus}, :/ => Proc.new{divide}, :* => Proc.new{times} } 
    tokens(pol).reverse.chunk{|n| n.is_a?(Integer)}.each{|e,a| e == true ? a.reverse.each{|a| push(a) } : a.each {|a| or 
der.push(a) }} 
    order.reverse.each {|o| (opps[o].call) } 
    end 

這個版本

  • 店特效,簡單地調用你的方法
  • 使用Proc.call實際調你的方法
+1

男人,我的大腦是左右搖擺!非常感謝 - 這正是問題所在!這可能不是預期的教訓,但這絕對是我今天最大的突破! – adamrabbit

+0

不客氣:-)請考慮接受我的答案,如果它解決了你的問題。 –

+1

哎呀,對不起...我只是意識到這個複選標記意味着! – adamrabbit