除了.evaluate方法外,我的代碼似乎都能正常工作。從程序我很努力去理解爲什麼我會在我的RPN計算器中收到一個錯誤消息
Failures:
1) RPNCalculator evaluates a string
Failure/Error: expect(calculator.evaluate("1 2 3 * +")).to eq(
NoMethodError:
undefined method `times' for [1, 2, 3]:Array
# ./lib/12_rpn_calculator.rb:78:in `block in evaluate'
# ./lib/12_rpn_calculator.rb:75:in `each'
# ./lib/12_rpn_calculator.rb:75:in `evaluate'
# ./spec/12_rpn_calculator_spec.rb:144:in `block (2 levels) in <top (required)>'
Finished in 0.00381 seconds (files took 0.10201 seconds to load)
9 examples, 1 failure
Failed examples:
rspec ./spec/12_rpn_calculator_spec.rb:143 # RPNCalculator evaluates a string
:
我收到錯誤消息
class RPNCalculator
def initialize
@calculator = Array.new
end
def push(x)
@calculator << x
end
def value
@calculator.last
end
def plus
error_message
sum = @calculator.pop + @calculator.pop
@calculator << sum
end
def minus
error_message
#@calculator.reverse!
#difference = @calculator.pop - @calculator.pop
first = @calculator.pop
second = @calculator.pop
difference = second - first
#
@calculator << difference
end
def divide
error_message
@calculator = @calculator.map {|n| n.to_f}
divisor = @calculator.pop ; dividend = @calculator.pop
quotient = (dividend/divisor)
@calculator << quotient
end
def times
error_message
puts @calculator.inspect
@calculator.map! {|n| n.to_f}
product = @calculator.pop * @calculator.pop
@calculator << product
end
def error_message
raise "calculator is empty" if @calculator.size < 2
end
def tokens(string)
operators = ["+", "-", "/", "*"]
string.split.map! {|i|
if operators.include?(i)
i.to_sym
else
i.to_i
end
}
end
def evaluate(rpn)
@calculator = tokens(rpn).select {|t| t.is_a?Integer}
operators = tokens(rpn).select{|t| t.is_a?Symbol}
operators.each {|n|
@calculator.plus if n == :+
@calculator.minus if n == :-
@calculator.times if n == :*
@calculator.divide if n == :/ }
end
end
在我看來,該.times方法應該用於數組。所以,我想了解發生了什麼。有一些基本問題嗎?還是有錯字?一般來說,爲什麼我會收到錯誤消息?
編輯:這裏有我需要通過規格:
require "12_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
expect(calculator.value).to eq(5)
end
it "adds three numbers" do
calculator.push(2)
calculator.push(3)
calculator.push(4)
calculator.plus
expect(calculator.value).to eq(7)
calculator.plus
expect(calculator.value).to eq(9)
end
it "subtracts the second number from the first number" do
calculator.push(2)
calculator.push(3)
calculator.minus
expect(calculator.value).to eq(-1)
end
it "adds and subtracts" do
calculator.push(2)
calculator.push(3)
calculator.push(4)
calculator.minus
expect(calculator.value).to eq(-1)
calculator.plus
expect(calculator.value).to eq(1)
end
it "multiplies and divides" do
calculator.push(2)
calculator.push(3)
calculator.push(4)
calculator.divide
expect(calculator.value).to eq((3.0/4.0))
calculator.times
expect(calculator.value).to eq(2.0 * (3.0/4.0))
end
it "resolves operator precedence unambiguously" do
# 1 2 + 3 * => (1 + 2) * 3
calculator.push(1)
calculator.push(2)
calculator.plus
calculator.push(3)
calculator.times
expect(calculator.value).to eq((1+2)*3)
@calculator = RPNCalculator.new
# 1 2 3 * + => 1 + (2 * 3)
calculator.push(1)
calculator.push(2)
calculator.push(3)
calculator.times
calculator.plus
expect(calculator.value).to eq(1+(2*3))
end
it "fails informatively when there's not enough values stacked away" do
expect {
calculator.plus
}.to raise_error("calculator is empty")
expect {
calculator.minus
}.to raise_error("calculator is empty")
expect {
calculator.times
}.to raise_error("calculator is empty")
expect {
calculator.divide
}.to raise_error("calculator is empty")
end
# extra credit
it "tokenizes a string" do
expect(calculator.tokens("1 2 3 * + 4 5 - /")).to eq(
[1, 2, 3, :*, :+, 4, 5, :-, :/]
)
end
# extra credit
it "evaluates a string" do
expect(calculator.evaluate("1 2 3 * +")).to eq(
((2 * 3) + 1)
)
expect(calculator.evaluate("4 5 -")).to eq(
(4 - 5)
)
expect(calculator.evaluate("2 3 /")).to eq(
(2.0/3.0)
)
expect(calculator.evaluate("1 2 3 * + 4 5 - /")).to eq(
(1.0 + (2 * 3))/(4 - 5)
)
end
end
,你可以看到,「.times」是,我打算在陣列工作類中定義的方法。我想我會「評估」一個字符串,將其轉換爲一個數組,然後在其上運行自定義方法,但我不知道該怎麼做。
'@ calculator'是一個數組,所以爲了調用'.times'就可以了,陣列需要知道如何迴應'.times'。我想你想在RPNCalculator的一個實例上調用'.times',而不是在一個Array上。既然你是從一個實例方法調用'.times',你可以調用'self.times',或者遵循Ruby約定,只要省略'self'並且調用'if == ==:*'。整個事情可能會有點混亂,如果你的操作數數組被稱爲像'operands'而不是'calculator.' – moveson
*在我看來,.times方法應該適用於數組。* - 你可以通過這裏是類Array的ruby文檔:http://ruby-doc.org/core-2.3.3/Array.html。你在哪裏看到times()方法? *一般來說,爲什麼我會收到錯誤信息?*因爲您不能寫:[1,2,3] .times()和'@calculator = [1,2,3]; @ calculator.times()'因爲Array類沒有定義'times()'方法。 – 7stud
歡迎來到Stack Overflow。請閱讀「[mcve]」。它可以幫助我們在將代碼減少到複製問題所需的最低限度時爲您提供幫助。而且,在這個過程中,你經常會發現自己的問題。 –