2015-02-21 2 views
0

Я пишу программу, которая толкает числа Фибоначчи в массив, используя Ruby. Код работает, но я не могу обернуть вокруг , почему он работает.Я не знаю, почему эта последовательность Ruby Fibonacci работает

Эта часть Я понимаю, что это уравнение Фибоначчи:

fib_array = [] 

def fib (n) 
    return n if n <= 1 
    fib(n - 1) + fib(n - 2) 
end 

Это то, что я не понимаю:

10.times do |x| 
    fib_array << fib(x) 
end 

print fib_array 

Я написал это хватаясь за соломинку, и она работает. Я не понимаю, почему. Я не кормил его номером, чтобы начать, делает ли Руби значение 0? Кроме того, как он знал, чтобы комбинировать числа вместо печати [0, 0, 0 ...]? Прошу прощения, если это вопрос, который мне нужен, но я нахожусь в убытке.

ответ

2

Похоже, что нижняя часть кода просто вызывает функцию fib на x=0, x=1 ... x=9 и сохраняет ее возвращаемое значение в конце массива. Когда times вызывается с переменной итерации (x), она начинается с 0 и увеличивается на каждой итерации через цикл. Вы никогда не кормили его значением, однако ему удается успешно решить проблему, и переменная итерации x передается как параметр в fib.

2

Вторая часть кода говорит:

«От экземпляра 10 класса Integer, вызовите метод times с данным блоком» (метод «Recive» блок-неявно).

Что такое блок? Небольшая часть кода между {braces} или do-end (как и вы).

Метод times называется «итератором». И это будет yield 0,1,2, .., 9 (в вашем случае). Итератор и оператор yield всегда вместе. Подумайте, что yield похож на return с памятью, когда вы ищете дополнительную информацию.

Таким образом, ваш код может быть переписывание как:

10.times { |x| fib_array << fib(x) } 

И позвонит, блок вы проходите, на каждом yield, что метод times делает. Вызов метода << (добавление) к результату fib(x) в вашем массиве.

0

Мы имеем:

def fib (n) 
    return n if n <= 1 
    fib(n - 1) + fib(n - 2) 
end 

, который вы понимаете. Во-первых, давайте посмотрим, что первые 5 чисел Фибоначчи ::

fib_array = [] 
5.times do |x| 
    fib_array << fib(x) 
end 
fib_array 
    #=> [0, 1, 1, 2, 3] 

Теперь давайте разберем это вниз и посмотреть, что происходит. Сначала просмотрите документы для метода times. Чтобы найти их, нам нужно знать, из какого класса или модуля этот метод, потому что так организованы документы. Как 5.class #=> Fixnum, мы можем посмотреть документы для Fixnum. Хммм. times нет. По-видимому, он был унаследован от другого класса.Давайте проверим:

Fixnum.ancestors 
    #=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject] 

Integer включает Fixnum и BigNum, Numeric включает Integer и Float. (3.14).times не имеет смысла, поэтому появляется times определяется в Integer, и так есть: Integer#times. Определив его, он наследуется как Fixnum, так и Bignum.

Вот прямой способ, чтобы определить, где метод пришел из:

5.method(:times).owner #=> Integer 

Это не важно понять это сейчас, но вы найдете его под рукой, как вы получаете опыт работы с Ruby.

ОК, документы говорят, что times возвращает значение, если задано блок, или перечислитель, если нет. Давайте забудем о блоке момент и посмотреть на счетчику, который возвращается:

enum = 5.times   #=> #<Enumerator: 5:times> 

Метод Enumerator#each передает элементы счетчику enum к его блоку:

do |x| 
    fib_array << fib(x) 
end 

назначая их к переменной блока x. Чтобы увидеть содержимое счетчику, преобразовать его в массив:

enum.to_a   #=> [0, 1, 2, 3, 4] 

Результат:

fib_array = [] 
enum.each do |x| 
    fib_array << fib(x) 
end 
fib_array 
    #=> [0, 1, 1, 2, 3] 

, который, конечно, тот же самый результат, который мы получили ранее. Теперь давайте посмотрим, что происходит шаг за помощью, с помощью метода Enumerator#next для извлечения каждого элемента счетчику:

x = enum.next  #=> 0 
fib(x)    #=> 0 
fib_array << fib(x) #=> [0] 

x = enum.next  #=> 1 
fib(x)    #=> 1 
fib_array << fib(x) #=> [0, 1] 

x = enum.next  #=> 2 
fib(x)    #=> 1 
fib_array << fib(x) #=> [0, 1, 1] 

x = enum.next  #=> 3 
fib(x)    #=> 2 
fib_array << fib(x) #=> [0, 1, 1, 2] 

x = enum.next  #=> 4 
fib(x)    #=> 3 
fib_array << fib(x) #=> [0, 1, 1, 2, 3] 

print fib_array  # [0, 1, 1, 2, 3] 

Это все есть на него.

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