Итак, приглядимся повнимательнее к нашей новой программе. Обратите
внимание на первые строки, начинающиеся с хэш символа (#). В Ruby все,
что в одной строке идет после хэш символа является комментарием и
игнорируется интерпретатором. Первая строка файла – особый случай, и под
Unix-подобными операционными системами говорит шеллу (shell) как
запускать данный файл. Остальные комментарии служат лишь для пояснений
кода.

Наш `say_hi` метод стал немного более сложным:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># Сказать всем привет</span>
<span class="k">def</span> <span class="nf">say_hi</span>
  <span class="k">if</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">nil?</span>
    <span class="nb">puts</span> <span class="s2">"..."</span>
  <span class="k">elsif</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"each"</span><span class="p">)</span>
    <span class="c1"># @names это некий список, итерируй!</span>
    <span class="vi">@names</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">name</span><span class="o">|</span>
      <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">!"</span>
    <span class="k">end</span>
  <span class="k">else</span>
    <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">#{</span><span class="vi">@names</span><span class="si">}</span><span class="s2">!"</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

Теперь он смотрит на переменную `@names`, чтобы принять решение. Если
ее значение nil, он просто печатает три точки. Нет смысла приветствовать
несуществующее, верно?

## Циклы и повторы – также известные как итерации

Если объект, записанный в переменной `@names`, откликается на метод
`each`, значит он является объектом, на котором вы можете итерировать.
И, итерируя по нему, вы можете приветствовать каждого человека за раз.
И, наконец, если переменная `@names` является чем-то совсем другим,
просто превратим её в строку автоматически и поприветствуем.

Давайте взглянем на итератор повнимательнее:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="vi">@names</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">name</span><span class="o">|</span>
  <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">!"</span>
<span class="k">end</span></code></pre></figure>

`each` – это метод, который принимает блок кода и запускает этот блок
кода для каждого элемента в списке. И в примере выше код между `do` и
`end` – это просто некий блок. Блок – это что-то вроде анонимной функции
или `лямбды`. Переменная между знаками (|) – это параметр для данного
блока, как раз тот самый элемент списка, на которым будет производится
действие в блоке кода.

Что происходит здесь, это то, что каждая запись в списке – `name` –
привязана к элементу в списке, и, таким образом, выражение `puts "Hello
#{name}!"` будет выполнено с этим элементом.

Большинство других языков программирования поддерживают прохождение по
списку при помощи цикла `for`, который в C выглядит примерно так:

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">for</span> <span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">number_of_elements</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
  <span class="n">do_something_with</span><span class="p">(</span><span class="n">element</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span></code></pre></figure>

Это работает, но это не так элегантно. Вам нужно заводить переменную типа
`i`, понимать, сколько элементов в списке, и объяснять языку, как он
должен проходить по списку. Путь Ruby намного элегантней: все детали
исполнения скрыты внутри `each` метода – и все что вам нужно сделать
– это сказать: что нужно сделать с элементами списка. Внутри метод
`each` вызывает `yield "Albert'"`, затем `yield "Brenda"` и так далее с
остальными именами.

## Блоки: прекрасные блёстки на грани Ruby

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

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># Сказать всем пока</span>
<span class="k">def</span> <span class="nf">say_bye</span>
  <span class="k">if</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">nil?</span>
    <span class="nb">puts</span> <span class="s2">"..."</span>
  <span class="k">elsif</span> <span class="vi">@names</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"join"</span><span class="p">)</span>
    <span class="c1"># Объединить все значения из списка через запятую</span>
    <span class="nb">puts</span> <span class="s2">"Goodbye </span><span class="si">#{</span><span class="vi">@names</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">", "</span><span class="p">)</span><span class="si">}</span><span class="s2">.  Come back soon!"</span>
  <span class="k">else</span>
    <span class="nb">puts</span> <span class="s2">"Goodbye </span><span class="si">#{</span><span class="vi">@names</span><span class="si">}</span><span class="s2">.  Come back soon!"</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

Метод `say_bye` не использует `each` – вместо этого он проверяет, что
`@names` откликается на метод `join`, и если так – использует его. В
другом случае он просто печатает переменную в виде строки. Этот метод
не волнует настоящий *тип* переменной, он просто действует в зависимости
от методов, которые тот поддерживает. Это также известно под названием
"Duck Typing" (Утиная типизация), как в известной фразе – "если оно
ходит как утка и крякает как утка – это утка". Выигрыш от этого в том,
что вам не обязательно ограничивать типы переменных, которые
поддерживаются. Если кто-то захочет использовать ваш метод с неким новым
классом списка, пока тот поддерживает вызов метода `join` с аналогичной
другим спискам семантикой – все будет работать как запланировано.

## Запускаем скрипт

Итак, это был MegaGreeter класс; остальное в файле – это лишь вызовы
метода на этом классе. Последний трюк, на который стоит обратить
внимание – это следующая строка:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">if</span> <span class="kp">__FILE__</span> <span class="o">==</span> <span class="vg">$0</span></code></pre></figure>

`__FILE__` – это магическая переменная, которая содержит имя текущего
файла. `$0` – это имя файла, которое было использовано при запуске
программы. Данная проверка говорит: "Если это тот самый файл, который
был запущен изначально…". Это позволяет файлу быть использованным как
библиотека и не выполнять код в данном контексте. Но если файл
используется как выполняемый – тогда выполняем этот код.

## Считайте, что вы в теме

Итак, это конец краткого тура по Ruby. Там еще столько для изучения:
различные структуры, которые предлагает Ruby; использование блоков и
`yield`; модули и примеси – и многое-многое другое. Я надеюсь, что эти
небольшие примеры оставят у вас приятное послевкусие от Ruby – и вы
захотите узнать его еще лучше!

Если так, пожалуйста, просмотрите нашу
[Документацию](/ru/documentation/), которая содержит в себе ссылки на
руководства и введения – все они бесплатно доступны онлайн.
