Области видимости переменных

Материал этой главы не сразу укладывается в голове, потому что правила областей видимости, хоть и интуитивны, но не так просты. Советую попрактиковаться с областями видимости.

Существует три типа областей видимости переменных: глобальная, мягкая локальная и жесткая локальная.

Глобальная область видимости

В отличие от многих языков программирования, в Julia не существует одной общей области видимости на всю программу. Причины такого решения очевидны: опыт предыдущих языков показал, что глобальные, в глобальном смысле, переменные - это зло. Любое определение должно иметь четкую адресацию в пространстве имен и принадлежать определенному модулю. Поэтому, то, что в Julia называется глобальной областью, не распространяется дальше модуля. Интерактивная среда REPL вводит свою глобальную область: модуль Main. Таким образом, все, что вы объявляете в REPL, принадлежит модулю Main. Это можно увидеть:

julia> f(x)=x+1
f (generic function with 1 method)

julia> which(:f)
Main

Переменные, объявленные на верхнем уровне REPL, будут глобальными, принадлежащими Main. Если вы напишете программу, поместив код в файле вне всякого модуля - этот код будет принадлежать тоже Main. Любая переменная верхнего уровня любого модуля будет глобальной переменной (этого модуля).

Локальная область видимости

Julia использует модель лексических областей, а не динамических. Лексическая родительская область окружает функцию или структуру в момент определения. Не надо путать ее с динамической родительскую областью видимости (областью вызывающего кода).

Локальная область видимости разделяется на жесткую и мягкую. Есть у них общие свойства. У них нет своего квалификатора имени, как у модуля. Переменная введенная в локальной области не переходит потом в родительскую область видимости, однако переменные из родительской области могут быть унаследованы локальной областью. Локальные области могут быть вложенными.

Ключевые слова local и global, поставленные перед переменной в локальной области, позволяют явно указать, к какой области будет относиться переменная.

Жесткая локальная область видимости

Теперь зайдем с другого конца. Любая функция, должна гарантировать одинаковое поведение вне зависимости от окружения, существующего в момент ее выполнения, динамической. Это тоже очевидно, иначе мы бы не смогли безопасно вызывать любую функцию в нашем коде: "А вдруг она внутри использует переменные с теми же именами, что у нас уже определены?" С этим тоже согласятся программисты на любом языке. Тоже самое касается анонимных функций.

Разумно под это строгое правило так же подвести любую изменяемую или неизменяемую структуру, имеющую собственные поля (если бы в Julia существовали классы в терминах ООП, то они тоже попали бы сюда).

Итого, любая функция, в том числе, анонимная функция, в том числе do-блок, а так же структура (struct) вводит такую само собой разумеющуюся для любого программиста форму области видимости, называемую в Julia жесткой областью видимости.

Функции и структуры в момент их определения могут наследовать (замыкать) переменные из родительской глобальной области видимости за исключением, когда существует попытка изменить переменную из глобальной области или переменная явно помечена как local. Иными словами, по умолчанию жесткая область видимости унаследует из лексической глобальной области переменные только для чтения. Это согласуется с тем, что , например, нужно иметь возможность создавать замыкания. Ключевое слово global разрешит доступ для записи глобальной переменной. Таким образом, случайно изменить глобальную переменную из функции программист не сможет.

Интересно, что в случае объявления вложенных функций (одна объявлена в теле другой) область действия внешней по отношению к внутренней является родительской, но не глобальной. При этом внутренняя функция наследует все переменные из внешней как для чтения, так и для записи.

Мягкая локальная область видимости

Мягкая локальная область - это циклы for, while, списковые включения (синтаксис создающий генераторы и другие итераторы с помощью круглых или квадратных скобок), блоки try-catch-finally и let.

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

Ключевое слово local заставляет переменную быть строго локальной.

Блоки if и begin

Они, вообще, не вводят никакую область видимости.

results matching ""

    No results matching ""