Evgenii Legotckoi
Evgenii Legotckoi25 червня 2016 р. 02:22

Посібник користувача №09 - Ruby - ітератори

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

Дієслово iterate означає робити будь-яку річ багато разів, і ви знаєте, що ітератор є чимось, що виконує деяку річ багато разів.

Коли ми пишемо код, ми маємо працювати з циклами у багатьох ситуаціях. У C ми використовуватимемо for або while. Наприклад,

char *str;
for (str = "abcdefg"; *str != '\0'; str++) {
  /* здесь идёт обработка символа */
}

C синтаксис for(...) надає абстракцію за допомогою із створенням циклу, але перевірка str на null символ вимагає від програміста знати деталі про внутрішній структурі рядка. Це створює відчуття того, що C є низькорівневою мовою. Мови високого рівня відзначені більш гнучкою підтримкою рядків. Розглянемо наступний shell скрипт sh*:

#!/bin/sh

for i in *.[ch]; do
  # ... here would be something to do for each file
done

Усі вихідні та заголовні файли C обробляються в поточній директорії, і команда shell обробляє деталі файлів підбираючи та змінюючи імена файлів один за одним. Цей рівень є більш високим, ніж у C, чи не так?

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

Отже, об'єктно-орієнтована мова включає деякі можливості для ітерації. Деякі мови надають спеціальні класи для цього. А Ruby дозволяє прямо визначати ітератори.

Рядок Ruby має деякі корисні ітератори:

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

each_byte є ітератором кожного символу в рядку. Кожен символ міститься в локальній змінній c . Це може бути трансльовано в щось схоже на C код.

ruby> s="abc";i=0
   0
ruby> while i<s.length
    |    printf "<%c>", s[i]; 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 працює подібно 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

Ви зрозуміли, що це ітератор? Є кілька обмежень в оригінальних ітераторах, але фактично, щоразу, коли ви визначаєте новий тип даних, часто буває зручно визначити відповідні ітератори для цього. У цьому випадку наведені вище приклади не дуже корисні. Ми можемо про це поговорити після того, як краще зрозуміємо, що таке класи.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 11:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 11:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 22:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi01 листопада 2024 р. 00:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 18:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 17:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 21:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi25 червня 2024 р. 01:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 17:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 13:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 19:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Слідкуйте за нами в соціальних мережах