.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は、」私は配列上で動作するように意図したクラスで定義されたメソッドです。文字列を配列に変換してカスタムメソッドを実行することによって文字列を評価すると想像しましたが、その方法はわかりません。
それに '.times'を呼び出すために、配列がどのように知っておく必要がありますので、' @のcalculator'は、配列であります'.x 'に応答します。私は、配列ではなく、RPNCalculatorのインスタンスで '.times'を呼びたいと思います。インスタンスメソッドから '.times'を呼び出すので、' self.times'を呼び出すか、Rubyの規約に従うために 'self'を省略し、' n ==:* 'なら' times 'を呼び出します。オペランドの配列が 'calculator 'の代わりに' operand'のように呼ばれていた場合は、全体が少し混乱するかもしれません。 – moveson
* .timesメソッドは配列のために機能するはずです* ArrayクラスのRubyドキュメントはこちら:http://ruby-doc.org/core-2.3.3/Array.html。 times()メソッドはどこにありますか? *一般的に、なぜエラーメッセージが表示されるのですか?*あなたは '[1,2,3] x()'や '@calculator = [1、2、3];と書くことができません。 @ calculator.times() 'Arrayクラスは' times() 'メソッドを定義していないためです。 – 7stud
ようこそスタックオーバーフローへ。 「[mcve]」をお読みください。問題を再現するのに必要な最低限のコードに減らすと、役立ちます。そして、そのプロセスの間にあなた自身が問題を見つけることがよくあります。 –