Генератор чисел Фибоначчи (пример из книги)
Задание
- Сохраните исходный код, приведенный внизу страницы в файл
fibonacci.rb
- В командной строке перейдите в директорию, где находится
fibonacci.rb
, и наберите команду rdoc fibonacci.rb
. Будет создана директория doc
. Откройте в браузере файл doc/index.html
.
- Напишите четыре примера использования модуля
Fibonacci
: по два примера на каждую из функций sequence
и upto
.
- Изучите ключевое слово
lambda
.
- Как определен оператор квадратные скобки для экземпляров класса
Proc
? Как это используется в данном коде?
Исходный код
# This module encapsulates functionality related to the
# generation of Fibonacci sequences.
#--
# Copyright (c) 2004 Dave Thomas, The Pragmatic Programmers, LLC.
# Licensed under the same terms as Ruby. No warranty is provided.
module Fibonacci
# Calculate the first _count_ Fibonacci numbers, starting with 1,1.
#
# :call-seq:
# Fibonacci.sequence(count) -> array
# Fibonacci.sequence(count) {|val| ... } -> nil
#
# If a block is given, supply successive values to the block and
# return +nil+, otherwise return all values as an array.
def Fibonacci.sequence(count, &block)
result, block = setup_optional_block(block)
generate do |val|
break if count <= 0
count -= 1
block[val]
end
result
end
# Calculate the Fibonacci numbers up to and including _max_.
#
# :call-seq:
# Fibonacci.upto(count) -> array
# Fibonacci.upto(count) {|val ... } -> nil
#
# If a block is given, supply successive values to the
# block and return +nil+, otherwise return all values as an array.
def Fibonacci.upto(max, &block)
result, block = setup_optional_block(block)
generate do |val|
break if val > max
block[val]
end
result
end
private
# Yield a sequence of Fibonacci numbers to a block.
def Fibonacci.generate
f1, f2 = 1, 1
loop do
yield f1
f1, f2 = f2, f1+f2
end
end
# If a block parameer is given, use it, otherwise accumulate into an
# array. Return the result value and the block to use.
def Fibonacci.setup_optional_block(block)
if block.nil?
[ result = [], lambda {|val| result << val } ]
else
[ nil, block ]
end
end
end