Testfirst.org - rpn_calculator - как я могу передать переменную между методами?
Я пытаюсь сделать этот урок, и мне явно не хватает чего-то явно очевидного!
требует "rpn_calculator" описать RPNCalculator сделать attr_accessor: калькулятор прежде чем делать @calculator = RPNCalculator.new конец это "добавляет два числа" сделать calculator.push(2) calculator.push(3) calculator.plus calculator.value.should == 5 конец... # дополнительный кредит это "оценивает строку" делать calculator.evaluate("1 2 3 * +").should == ((2 * 3) + 1) ... конец конец
Все работает для моих глаз новичка, кроме @numbers. установка @numbers из метода вычисления не влияет на @numbers в других методах, и я действительно не понимаю, почему. Я перепробовал все, что мог, включая изменение @numbers на @@ numbers, но, похоже, ничего не помогло. Я мог бы просто оценить строку в методе оценки... но у меня уже есть такой хороший метод плюс, который я могу использовать!
класс RPNCalculator attr_accessor: числа инициализация по умолчанию @numbers = [] конец def push (n) @ Numbers.push (п) конец Def Plus @numbers.length > 1? @numbers.push(@numbers.pop(2).reduce(:+)): ошибка конец Def минус @numbers.length > 1? @numbers.push(@numbers.pop(2).reduce(:-)): ошибка конец делить деление @numbers.length > 1? @numbers.push(@numbers.pop(2).inject{|x,y| x.to_f / y}): ошибка конец раз @numbers.length > 1? @numbers.push(@numbers.pop(2).reduce(:*)): ошибка конец значение по умолчанию @value = @numbers[-1] конец токены def (pol) pol.split(' ').map{|n| n.to_i.to_s == n? n.to_i: n.to_sym} конец определите (pol) заказ = [] opps = {:+ => плюс,:- => минус,:/ => делить,:* => раз} Маркеры (POL).reverse.chunk{| п | n.is_a (Integer)} каждый {|?. е, а | е == правда? a.reverse.each{| | push(a) }: a.each {|a| order.push(a) }} order.reverse.each {|o| (opps[o]) } конец дефолт начать поднять Exception.new("калькулятор пуст") конец конец конец
В результате происходит возврат плюса, потому что @numbers пусто....
RPNCalculator добавляет два числа добавляет три числа вычитает второе число из первого числа добавляет и вычитает умножает и делит решает приоритет оператора однозначно терпит неудачу информативно, когда не хватит значений, сложенных по токену, разбивает на строки строку (FAILED - 1) Сбои: 1) RPNCalculator оценивает строку Failure/Error: calculator.evaluate("1 2 3 * +").should == Исключение: калькулятор пуст # ./12_rpn_calculator/rpn_calculator.rb:59:in `fail' # ./12_rpn_calculator/rpn_calculator.rb:14: в блоке "плюс" # ./12_rpn_calculator/rpn_calculator.rb:39:in "оценить" # ./12_rpn_calculator/rpn_calculator_spec.rb:134:in `блок (2 уровня) в '
Благодаря Frank Schmitt меня все получилось. Видимо, не просто хранить методы в хешах.
Правильный метод оценки:
определите (pol) @numbers = [] # потому что это делает 4 теста без очистки @numbers opps = {:+ => Proc.new {plus},:- => Proc.new{минус},:/ => Proc.new{разделяй},:* => Proc.new{times} } # метод в проц, спасибо Фрэнк:D Маркеры (POL).chunk{| п | n.is_a (Integer)} каждый {|?. е, а | е == правда? a.each{| | push(a) }: a.each {|o| (opps[o].call) }} массиве @numbers[0] конец
1 ответ
По-видимому, Ruby вызывает методы, как только вы сохраняете их в своем хэше. Чтобы исправить это, вы можете использовать эту модифицированную версию вашего кода:
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
Эта версия
- хранит Procs внутри хеша opps, который просто вызывает ваши методы
- использует Proc.call для фактического вызова ваших методов