2013-04-03 3 views
0

Кто-нибудь знает, почему этот код:рубин ошибка рекурсии

sum=0 
def get_sum n 
    return sum if n<1 
    sum=sum+n 
    get_sum(n-1) 
end 

get_sum 10 

дает мне это?

rb:3:in `get_sum': undefined local variable or method `sum' for main:Object (NameError) 
from 1.rb:8:in `<main>' 

Код имеет смысл, и вы можете понять, что он делает.

ответ

3

Нормальные переменные, объявленные вне функции, являются не доступны внутри функции.

Вы можете использовать префикс sum с $, чтобы сделать его глобальную переменную (как правило, не является хорошей идеей.)

$sum=0 
def get_sum n 
    return $sum if n<1 
    $sum=$sum+n 
    get_sum(n-1) 
end 

get_sum 10 
#= 55 

Если у вас есть реальный тестовый случай, когда вы хотите сделать это, я могу предложить подходящий если хотите.

+0

спасибо! Я просто играл с функциональным рубином –

+0

Если вы играете с функциональным Ruby, вы должны использовать функции, а не методы. Или точнее: блоки. –

+0

Кроме того, изменяемые переменные и функциональное программирование являются взаимоисключающими. –

0

Прежде чем использовать его, вы никогда не инициализировали переменную sum.

Вы можете полностью избежать использования этой переменной, так как она ничего не делает:

def get_sum n 
    return 0 if n<1 
    get_sum(n-1) + n 
end 

get_sum 10 
1

Как писал @Dogbert, нормальные переменные, объявленные вне функции не доступны внутри функция.

Это подход, который не использует глобальные переменные (которые не подходят для рекурсии):

def get_sum(n, sum = 0) 
    return sum if n<1 
    get_sum(n-1, sum+n) 
end 

get_sum(10) #=> 55 
2

Вместо того чтобы использовать глобальную переменную, другой метод, использующий рекурсию бы, как это (ограничивается стека глубина, я думаю):

def get_sum(n) 
    return n if n < 1 
    n + get_sum(n - 1) 
end 

sum = get_sum(10) 

Если вы когда-либо использовать реализацию Ruby, который предлагает хвостовую оптимизацию (я не знаю ни реализации, которые делают), ProGNOMmers's method будет немного лучше в стеке, но, как является быстрым тестом, превышающим максимальный уровень стека около n = 9000 или около того. Не то чтобы вы возвращались 9000 раз или что-то еще.

-1

Вы можете попробовать это:

def get_sum n 
    return n if n == 0 
    return n + get_sum(n-1) 
end 

В этой версии вам не нужно какое-либо глобальное создание экземпляра переменного (которая не является хорошей идеей), и вы на самом деле выполнить регрессивную сумму :)

+0

Тестирование для 'n == 0' не является адекватным. Что сделает ваш код, если он получит -1? Используйте '<' или '<='. –

+0

Это был не тот момент, который я обсуждал. Тем не менее, если вы хотите, чтобы ваш код принимал отрицательные целые числа, вам, вероятно, понадобится конкретный случай, когда n <0 учитывается. В противном случае просто не имеет смысла делать вид, что сумма (-3) = -3 – aherve

Смежные вопросы