Язык программирования Ruby имеет очень простую политику предпочтения локальных переменных другим типам. Это причина, по которой их определение не требует никаких сигилов (@/$) или заглавных букв. Это также затронуло диапазоны областей, реализовав понятие гейтов области:

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

Хотя для многих Ruby-программистов это может показаться незыблемой основой, есть способ обойти ее. Передавая блок, мы могли бы заменить ворота области действия гораздо более либеральным закрытием, которое берет область действия из окружающего контекста. Итак, давайте перепишем наш первоначальный экземпляр:

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

Также стоит отметить, что все локальные переменные, определенные внутри блоков, по-прежнему недоступны для областей над ними.

Хорошо. Но зачем вообще заморачиваться?

Подход Ruby по умолчанию умен. Это уменьшает количество потенциально опасных ситуаций и ускоряет отладку. Однако есть еще несколько случаев, когда мы могли бы преднамеренно избегать ворот области видимости, чтобы повысить производительность. Давайте возьмем этот простой пример: у нас есть машина времени и расстояния в поездке. Но мы хотим вычислить его скорость:

Каждый раз, когда мы вызываем наш метод, Ruby создает для него дополнительную область видимости и выполняет вычисления. Это может замедлить нашу программу. Однако, если мы предварительно вычислим скорость и перепишем def в define_method, мы сможем избежать любых потенциальных проблем с производительностью: