Уровень стека слишком глубокий в Ruby - PullRequest
6 голосов
/ 17 марта 2012
class MyClass
  def method_missing(name, *args)
    name = name.to_s
    10.times do
      number = rand(100)
    end
    puts "#{number} and #{name}"
  end  
end

Здравствуйте, я выполняю ruby, но в этой нерекурсивной функции я получаю слишком большую ошибку на уровне стека при использовании этого фрагмента кода.

1 Ответ

11 голосов
/ 17 марта 2012

Проблема с вашим кодом заключается в том, что переменная number, определенная внутри times(), выходит за рамки method_missing(). Таким образом, когда эта строка выполняется, Ruby интерпретирует ее как вызов метода на self.

В обычных случаях вы должны получить исключение NoMethodError. Однако, поскольку вы переопределили метод method_missing() для MyClass, вы не получите это исключение. Вместо этого, пока стек не переполнится, вызывается метод number().

Чтобы избежать таких проблем, попробуйте указать имена методов, которые разрешены. Например, допустим, вам нужно только вызвать методы try, test, and my_method для MyClass, а затем указать имена этих методов для method_missing(), чтобы избежать подобных проблем.

Как пример:

class MyClass
  def method_missing(name, *args)
    name = name.to_s
    super unless ['try', 'test', 'my_method'].include? name
    number = 0
    10.times do
      number = rand(100)
    end
    puts "#{number} and #{name}"
  end  
end

Если вам не нужен method_missing(), избегайте его использования. Есть несколько хороших альтернатив здесь .

...