Как разработчик Ruby, одной из фундаментальных концепций, которую нужно понимать, является переменная область — когда и где вы можете использовать переменные, созданные вами в программе. Некоторые из моих самых больших трудностей при написании программ на ранних этапах были в основном связаны с неполным пониманием того, как работает масштаб.

Опять же, область действия переменной указывает, где к ней можно получить доступ и использовать в программе. И эта область действия или «возможность использования» определяется тем, где создается сама переменная.

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

weekdays = [‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’,’Friday’]
phrase = “Thank God it’s”
weekdays.each do |day|
 praise = “Amen, “
 puts praise + phrase + “ “ + day 
end
=> Amen, Thank God it’s Monday
=> Amen, Thank God it’s Tuesday
=> Amen, Thank God it’s Wednesday
=> Amen, Thank God it’s Thursday
=> Amen, Thank God it’s Friday

Однако доступ к той же самой переменной невозможен из-за пределов блока, который находится вне его области действия.

puts praise
=> `<main>’: undefined local variable or method `praise’ for main:Object (NameError)

И наоборот, если переменная инициализируется вне блока, к ней можно получить доступ из блока. Обратите внимание, что наша переменная phrase в приведенном выше примере была создана таким образом, и мы смогли получить к ней доступ.

weekdays = [‘Monday’, ‘Tuesday’, ‘Wednesday’, ‘Thursday’,’Friday’]
phrase = “Thank God it’s”
weekdays.each do |day|
 praise = “Amen, “
 puts praise + phrase + “ “ + day 
end

Также важно отметить, что циклы и блоки — это не одно и то же, и каждый из них ведет себя по-разному при обработке переменной. Тот факт, что к циклу присоединено do…end, может ввести в заблуждение. При определении области действия переменной блок представляет собой d0…end или набор фигурных скобок {подобно этим, которые следуют сразу за методом. Например:

weekdays.each do |day|
  puts day
end 
OR
weekdays.each{|day| puts day}

Поскольку цикл не является блоком, он не определяет область действия переменной. Это означает, что переменные, инициализированные внутри цикла некоторого типа, могут использоваться как внутри, так и вне цикла. Обратите внимание, что мы можем получить доступ к переменной greeting как внутри, так и вне цикла.

a = 0 
while a < 4
 greeting = “Wassup!?”
 puts a.to_s + “ “ + greeting
 a += 1 
end
puts greeting + " from outside!"
=> 0 Wassup!?
=> 1 Wassup!?
=> 2 Wassup!?
=> 3 Wassup!?
=> Wassup!? from outside!

Итак, это относится к блокам и циклическим конструкциям, а как насчет методов? Как они относятся к переменным в связи с областью видимости? К этому моменту мне понадобилось некоторое время, чтобы привыкнуть. Оказывается, в отличие от блоков и циклов, методы создают собственную область видимости, которая отделена от обычного потока выполнения программы.

Переменная, инициализированная в методе, относится к этому методу. К нему нельзя получить доступ извне метода. Кроме того, метод не может получить доступ к переменным, инициализированным вне его.

my_number = 7 
def addition(number)
 number = 10
 number + number 
end
puts addition(my_number)
puts my_number
puts number 
=> 20
=> 7 
=>`<main>': undefined local variable or method `number' for main:Object (NameError)

Здесь мы инициализируем переменную my_number и определяем новый метод с именем дополнение. Затем мы помещаем возвращаемое значение передачи my_number в метод дополнения. Обратите внимание, что на выходе 20, а не 14, хотя мы добавляем переменную к самой себе внутри метода. Почему это?

Ответом на это является то, что переменная my_number переименовывается в number при передаче в метод addition. Затем переменной number присваивается значение 10 внутри метода. Таким образом, (число + число) = (10 + 10) = 20. Во втором положении мы видим, что значение my_number былонеизменным и это все еще 7. Между тем, попытка доступа к переменной number вне метода сложения приводит к ошибке. Это связано с тем, что number привязан к методу добавления и не может использоваться вне его.

Важно отметить, что есть некоторые нюансы в том, как Ruby работает с переменными, которые передаются методам. А именно, является ли Ruby языком передачи по значению или передачи по ссылке (на самом деле это и то, и другое, шшш). Это целая «черная банка червей», о которой, возможно, я расскажу в новом посте. Но, надеюсь, эта небольшая заметка поможет кому-то лучше понять, как работает переменная область видимости.