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 для фактического вызова ваших методов
Другие вопросы по тегам