» Главная
eXcode.ru » Статьи » Ruby
» Новости
» Опросы
» Файлы
» Журнал



Пользователей: 0
Гостей: 16





Штробление

Фотографии работ.

svs-demontaj.ru


Профнастил

Интернет-магазин. Кровельные и стеновые материалы.

mskrov.ru




Итераторы




Итераторы не являются чем-то, свойственным только Ruby. Они общеупотребительны в объектно-ориентированных языках программирования. Они также есть в Lisp, хотя там они не называются итераторами. Как бы то ни было, концепция итераторов не является близкой множеству людей, так что давайте рассмотрим ее более детально.

Глагол iterate (повторять) означает "проделывать одно и то же много (ну, несколько) раз, так что итератор (iterator) - это нечто, делающее одно и то же много раз.

Когда мы программируем, то нуждаемся в использовании циклов во множестве различных ситуаций. В С мы кодируем их, используя for или while. Например,



char *str;

for (str = "abcdefg"; *str != ′\0′; str++) {

/* process a character here */

}

Синтакс оператора C for(...) обеспечивает абстракцию, помогающую в создании циклов, но для проверки *str на null необходимо знание программистом деталей о внутреннем представлении строки. Это дает представление о С как о низкоуровневом языке программирования. Высокоуровневые языки отличает более гибкая поддержка ими итераторов. Посмотрите на скрипт sh :



#!/bin/sh



for i in *.[ch]; do

# ... этот код будет выполнен для каждой строки

done

Обрабатываются все исходники на С и хидеры в текущем каталоге , а shell заботится о деталях получения и подстановки имен файлов один за одним. Думаю, это работает на несколько более высоком уровне, чем С, а?

Можно покопать глубже: хотя и хорошо, что в языке есть поддержка для создания итераторов по встроенным типам данных, но разочаровывает, что когда необходима итерация по собственным типам данных, нужно возвращаться к низкоуровневым циклам. В ООП Пользователи часто создают один за другим собственные типы данных, так что такая ситуация может создать серьезные проблемы.

Так, каждый язык ООП включает в себя некоторые средства поддержки итераторов. В некоторых языках для этой цели существуют специальные классы; Ruby же позволяет определять итераторы напрямую.

В Ruby для типа String имеется несколько полезных итераторов:



ruby> "abc".each_byte{|c| printf "<%c>", c}; print "\n"

<a><b><c>

nil

each_byte - итератор для каждого символа в строке. Каждый символ подставляется в локальную переменную c. Это может быть представлено как нечто, весьма напоминающее код на С...



ruby> s="abc";i=0

0

ruby> while i<s.length

| printf "<%c>", s; i+=1

| end; print "\n"

<a><b><c>

nil

... как бы то ни было, итератор each_byte и концептуально проще, и более вероятно продолжит работать даже если класс String будет в будущем радикально изменен. Одно из преимуществ итераторов - это то, что они имеют тенденцию выживать в случае подобных изменений; в самом деле, это является одной из характеристик хорошего кодирования вообще. (Ну да, потерпите немного, мы также собираемся поговорить о том, что такое классы вообще).

Вот еще итератор для String - each_line.



ruby> "a\nb\nc\n".each_line{|l| print l}

a

b

c

nil

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

Оператор for, использованный в предыдущей главе, делает итерации тем же путем, что и итератор each. each для String делает то же самое, что и each_line, так что давайте перепишем предыдущий пример с for:



ruby> for l in "a\nb\nc\n"

| print l

| end

a

b

c

nil

Мы можем использовать управляющую команду retry в сочетании с повторяющимся циклом, так что данная итерация будет повторена с самого начала.



ruby> c=0

0

ruby> for i in 0..4

| print i

| if i == 2 and c == 0

| c = 1

| print "\n"

| retry

| end

| end; print "\n"

012

01234

nil

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



ruby> def repeat(num)

| while num > 0

| yield

| num -= 1

| end

| end

nil

ruby> repeat(3) { print "foo\n" }

foo

foo

foo

nil

При помощи retry, можно определить итератор, который будет работать так же, как и while, хотя это слишком медленно, чтобы быть практичным.



ruby> def WHILE(cond)

| return if not cond

| yield

| retry

| end

nil

ruby> i=0; WHILE(i<3) { print i; i+=1 }

012 nil

Понятно, что такое итератор? Есть некоторые ограничения, но Вы можете написать собственные итераторы; фактически, когда Вы создаете новый тип данных, то часто удобно определить подходящий для него итератор. В этом смысле приведенные выше примере не слишком полезны. Мы сможем говорить о практическом применении итераторов после того, как будем иметь лучшее представление о том, что же такое классы.

К началу статьи





Добавил: MadvEXДата публикации: 2007-10-08 09:57:06
Рейтинг статьи:3.22 [Голосов 9]Кол-во просмотров: 3208

Комментарии читателей

Всего комментариев: 0
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Как вы относитесь к рекламе на сайтах.
Отрицательно, терпеть ее не могу!
46% (95)
С пониманием
25% (51)
Пусть будет, если только по делу
15% (32)
Она мне безразлична!
11% (23)
Я ее обожаю!
3% (6)

Проголосовало: 208
Если ваш холодильник управляется системой windows95/98, то вам следует быть внимательным:
1)Установка и удаление новых продуктов не всегда происходит корректно, для безопасности следует отформатировать морозилку перед инсталяцией ещё не замороженных продуктов!
2)Несанкционированный доступ ваших соседей к вашему холодильнику может быть пресечён установкой пароля. В случае, если вы забыли пароль рекомендуется вызвать слесаря-сантехника для удаленного доступа через заднюю стенку аппарата...
3)Вообще, причин, по которым вы не сможете насладиться вкусом ваших продуктов очень много! (Заметьте, холодильних WinFroze позволяет наслаждаться ВИДОМ продукта в любое время, имея прозрачную дверцу).
Рейтинг: 1/10 (2)
Посмотреть все анекдоты

 
eXcode.ru » Статьи » Ruby