Evgenii Legotckoi
Шілде 10, 2016, 1:03 Т.Қ.

Пайдаланушы нұсқаулығы №22 - Ruby - Жергілікті айнымалылар

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

  1. ruby> $foo
  2. nil
  3. ruby> @foo
  4. nil
  5. ruby> foo
  6. ERR: (eval):1: undefined local variable or method `foo' for main(Object)

При первом назначении вы создаёте локальную переменную выполняя её объявление. Если обратиться к неинициализированной локальной переменной, то интерпретатор Ruby подумает об этом, как о попытке вызвать метод с этим именем; соответственно вы увидите сообщение об ошибке.


Как правило локальная переменная размещается в одном из следующих местоположений в коде:

  • proc{...}
  • loop{...}
  • def ... end
  • class ... end
  • module ... end
  • в теле программы (в том случае, если не подходит всё выше перечисленное)

В следующем примере defined? является оператором, который проверяет определён ли идентификатор. Он возвращает описание идентификатора, если он определён, или nil в противном случае. Как Вы видите, областью размещения bar является цикл loop ; когда мы выходим из цикла, тогда bar является неопределённым.

  1. ruby> foo = 44; print foo, "\n"; defined? foo
  2. 44
  3. "local-variable"
  4. ruby> loop{bar=45; print bar, "\n"; break}; defined? bar
  5. 45
  6. nil

Процедурные объекты, которые живут в той же разделяемой области независимо от локальных переменных, также относятся к той же области, что и переменные. Здесь, локальная переменная bar является разделяемой между main и процедурными объектами p1 и p2:

  1. ruby> bar=0
  2. 0
  3. ruby> p1 = proc{|n| bar=n}
  4. #<Proc:0x8deb0>
  5. ruby> p2 = proc{bar}
  6. #<Proc:0x8dce8>
  7. ruby> p1.call(5)
  8. 5
  9. ruby> bar
  10. 5
  11. ruby> p2.call
  12. 5

Заметьте,  что bar=0 в самом начале не может быть опущено; Это назначение гарантирует, что область видимости bar будет включена в p1 и p2. В противном случае p1 и p2 будет иметь каждый свою собственную переменную bar . И вызывая, p2 мы получим ошибку "undefined local variable or method".

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

  1. ruby> def box
  2. | contents = 15
  3. | get = proc{contents}
  4. | set = proc{|n| contents = n}
  5. | return get, set
  6. | end
  7. nil
  8. ruby> reader, writer = box
  9. [#<Proc:0x40170fc0>, #<Proc:0x40170fac>]
  10. ruby> reader.call
  11. 15
  12. ruby> writer.call(2)
  13. 2
  14. ruby> reader.call
  15. 2

Ruby является интеллектуальным относительно областей видимости. Очевидно, что в нашем примере переменная contents является разделяемой между reader и writer . Но мы можем также произвести множество пар reader-writer , используя box как определено выше; Каждая пара разделяет переменную contents , и пары не интерферируют друг с другом.

  1. ruby> reader_1, writer_1 = box
  2. [#<Proc:0x40172820>, #<Proc:0x4017280c>]
  3. ruby> reader_2, writer_2 = box
  4. [#<Proc:0x40172668>, #<Proc:0x40172654>]
  5. ruby> writer_1.call(99)
  6. 99
  7. ruby> reader_1.call
  8. 99
  9. ruby> reader_2.call
  10. 15

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз