我不知道为什么这个 Ruby 斐波那契数列有效
I don't know why this Ruby Fibonacci sequence works
我正在编写一个程序,使用 Ruby 将斐波那契数列推入数组。代码有效,但我无法理解 为什么 它有效。
这部分我明白了,就是斐波那契方程:
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
我写了这个抓住救命稻草,它有效。我不明白为什么。我没有给它一个开始的数字,Ruby 是不是意味着 0?另外,它怎么知道复合数字而不是打印 [0, 0, 0...]?如果这是一个愚蠢的问题,我深表歉意,但我不知所措。
看起来底部的代码只是调用 x=0, x=1 ... x=9
上的 fib
函数并将它的 return 值存储在数组的末尾。当使用迭代变量 (x) 调用 times
时,它从 0 开始并在循环的每次迭代中递增。你从来没有给它一个值,但是它成功地解决了迭代变量 x
作为参数传递给 fib
.
的问题
代码的第二部分说:
"From the instance 10
of the class Integer
, call the method times
with the given block"(方法"recive"隐含一个块)。
什么是区块? {braces}
或 do-end
之间的一小段代码(就像您所做的那样)。
方法 times
被调用,"iterator"。它会 yield
0,1,2,..,9(在你的情况下)。迭代器和 yield 语句总是在一起的。认为yield
就像return
有记忆,当你寻找更多信息时。
因此,您的代码可以重写为:
10.times { |x| fib_array << fib(x) }
它会在方法 times
的每个 yield
上调用你传递的块
做。调用方法 <<
(追加)到数组上 fib(x)
的结果。
我们有:
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
的文档。要找到它们,我们需要知道方法来自哪个 class 或模块,因为这就是文档的组织方式。作为 5.class #=> Fixnum
,我们可能会查看 Fixnum 的文档。嗯。 times
不存在。显然,它是从另一个 class 继承而来的。让我们检查一下:
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
return 如果给定块则为值,否则为枚举器。让我们暂时忘记块,看看 returned:
的枚举器
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]
仅此而已。
我正在编写一个程序,使用 Ruby 将斐波那契数列推入数组。代码有效,但我无法理解 为什么 它有效。
这部分我明白了,就是斐波那契方程:
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
我写了这个抓住救命稻草,它有效。我不明白为什么。我没有给它一个开始的数字,Ruby 是不是意味着 0?另外,它怎么知道复合数字而不是打印 [0, 0, 0...]?如果这是一个愚蠢的问题,我深表歉意,但我不知所措。
看起来底部的代码只是调用 x=0, x=1 ... x=9
上的 fib
函数并将它的 return 值存储在数组的末尾。当使用迭代变量 (x) 调用 times
时,它从 0 开始并在循环的每次迭代中递增。你从来没有给它一个值,但是它成功地解决了迭代变量 x
作为参数传递给 fib
.
代码的第二部分说:
"From the instance 10
of the class Integer
, call the method times
with the given block"(方法"recive"隐含一个块)。
什么是区块? {braces}
或 do-end
之间的一小段代码(就像您所做的那样)。
方法 times
被调用,"iterator"。它会 yield
0,1,2,..,9(在你的情况下)。迭代器和 yield 语句总是在一起的。认为yield
就像return
有记忆,当你寻找更多信息时。
因此,您的代码可以重写为:
10.times { |x| fib_array << fib(x) }
它会在方法 times
的每个 yield
上调用你传递的块
做。调用方法 <<
(追加)到数组上 fib(x)
的结果。
我们有:
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
的文档。要找到它们,我们需要知道方法来自哪个 class 或模块,因为这就是文档的组织方式。作为 5.class #=> Fixnum
,我们可能会查看 Fixnum 的文档。嗯。 times
不存在。显然,它是从另一个 class 继承而来的。让我们检查一下:
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
return 如果给定块则为值,否则为枚举器。让我们暂时忘记块,看看 returned:
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]
仅此而已。