Блоки и итераторы

Posted on Апрель 20, 2008. Filed under: programming ruby 2nd edition, ruby |

Вы можете использовать блоки для реализации обратных вызовов, передачи кусков кода и для реализации итераторов.

Дальше больше

Блоки представляют собой простые куски кода заключенные в фигурные скобки или между <i>do … end</i>
<pre>
<code>
{ puts «Hello»} #это блок
</code>
</pre>
<pre>
<code>
do #
club.enroll( person) # и это тоже
person.socialize #
end #
</code>
</pre>
Когда блок создан его можно ассоциировать с вызовом метода. Это делается помещением блока кода в конец строки содержащей вызов метода. Например, в следующем коде, блок, содержащий <i>puts «Hi»</i> ассоциирован с вызовом метода greet.
<pre>
<code>
greet { puts «Hi» }
</code>
</pre>
Если у метода есть параметры, они перечисляются перед блоком:
<pre>
<code>
verbose_greet(«Dave», «loyal customer») {puts «Hi»}
</code>
</pre>
Метод может вызвать ассоциированный блок один или несколько раз используя выражение <i>yield</i>. Оно похоже на вызов метода, который вызывает блок, ассоциированный с методом, содержащим <i>yield</i>.
Следующий пример показывает это в действии. Мы определим метод который вызывает yield два раза. Затем вызовем этот метод, поместив блок на той же линии после вызова (и после перечисления аргументов метода)
<pre>
<code>
def call_block
puts «Start of method»
yield
yield
puts «End of method»
end
call_block { puts «In the block» }
</code>
</pre>
результатом будет:
<pre>
<code>
Start of method
In the block
In the block
End of method
</code>
</pre>
Каждый вызов <i>yield</i> выводит на печать «In the block».
Блок кода можно вызывать с параметрами, передавая их через <i>yield</i>. Внутри блока просто перечислите аргументы, заключив их между вертикальными чертами (|).
<pre>
<code>
def call_block
yield(«hello», 99)
end
call_block {|str, num|}
</code>
</pre>
Блоки кода использеются повсюду для реализации итераторов: методы которые возвращают элементы последовательности взятые из некоторой коллекции, например, из массива.
<pre>
<code>
animals = %w( ant bee cat dog elk )
animals.each {|animal| puts animal }
</code>
</pre>
даст:
<pre>
<code>
ant
bee
cat
dog
elk
</code>
</pre>
Внутри класса <i>Array</i> мы бы воплотили итератор <i>each</i> следующим образом, используя псевдо-код:
<pre>
<code>
# внутри класса Array
def each
for each element # <- псевдо код
yield element
end
end
</code>
</pre>
Большинство конструкций перебора которые встроены в C или Java в Руби являются простыми методами, вызывающими ассоциированные блоки ноль или более раз.
<pre>
<code>
[ ‘cat’, ‘dog’, ‘horse’ ].each { |name| print name, » «}
5.times { print «*» }
3.upto(6) { |i| print i }
(‘a’..’e’).each { |char| print char }
</code>
</pre>
в результате дает нам
<pre>
<code>
cat dog horse *****3456abcde
</code>
</pre>
Мы просим объект 5 вызвать блок пять раз и затем просим объект вызвать блок, передавая последовательные значения пока они не достигнут значения 6. И в конце диапазон величин от a до e вызывает блок используя метод each.
Все это — вольный перевод <i>Dave Thomas — Programming ruby 2nd edition</i> (The Pragmatic Programmers’ Guide)

Реклама

Make a Comment

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

Liked it here?
Why not try sites on the blogroll...

%d такие блоггеры, как: