Книга: Язык программирования Euphoria. Справочное руководство

2.4.2 Сцена (область видимости)

2.4.2 Сцена (область видимости)

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

В Euphoria имеется множество предопределённых (так сказать, заранее объявленных, а точнее, встроенных) процедур, функций и типов. Все они объявляются автоматически перед стартом любой программы. Редактор Euphoria отображает их имена в малиновом цвете. Эти предопределённые имена не являются занятыми словами, и вы можете переопределить их своими собственными подпрограммами.

Каждое новое имя в вашей программе перед его дальнейшим использованием должно быть объявлено, а структурная единица программы (переменная, подпрограмма, константа) фигурирующая под этим именем, должна быть вами определена. Такая дисциплина, действующая в Euphoria, позволяет вам читать программу последовательно от начала и до конца без необходимости забегания вперёд, чтобы раскрыть значение заинтриговавшего вас слова, которое уже вовсю используется автором программы, но действительный смысл которого ещё окутан тайной, которая скрывается где-то в дебрях кода, спутанного как итальянские макароны в кастрюле. Тем не менее, если необходимость в опережающей ссылке на подпрограмму существует и оправдана упрощением кода, вы можете предусмотреть вызов подпрограммы по особому её номеру, значение которого будет вычислено в вашей программе позже, но не по имени, которое ещё не объявлено. Для этого в Euphoria имеются специальная функция, routine_id(), и, соответственно, подпрограммы call_func() или call_proc(), одна для функций, а другая для процедур. См. Часть II - Библиотека подпрограмм - Динамические вызовы.

В процедурах, функциях и типах разрешены рекурсивные вызовы, когда подпрограмма вызывает саму себя. Взаимная рекурсия, где подпрограмма A вызывает подпрограмму B, которая прямо или косвенно вызывает подпрограмму A, также возможна, но требует использования механизма routine_id().

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

Когда вы включаете библиотечный файл Euphoria в свой главный файл (см. 2.6 Специальные команды высшего уровня), то только переменные и подпрограммы, объявленные в библиотечном файле с использованием ключевого слова global, оказываются доступными или даже видимыми в вашем главном файле. Другие, не-глобальные, объявления в библиотечном файле видны интерпретатору только до конца библиотечного файла, и вы можете повторно использовать их имена, не опасаясь, что местные переменные, уже работающие в пределах библиотечного файла, будут в этом случае как-то задеты из вашего главного файла. И напротив, если вы попытаетесь обратиться к местной переменной или подпрограмме библиотечного файла по их именам из вашего главного файла, то получите аварийную остановку программы с сообщением об ошибке "not declared" - "не объявлено".

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

Иногда, используя библиотеки, разработанные другими программистами, вы будете сталкиваться с возникающими конфликтами имён. Один из авторов библиотек, используемых вами совместно, может дать своей подпрограмме то же самое глобальное имя, которое уже было занято другими авторами. Если у вас имеется исходный код, вы можете просто отредактировать одну из библиотек и исправить ситуацию, но тогда вы должны будете повторять это редактирование снова и снова по мере выхода новых версий используемой вами библиотеки. В Euphoria имеется более простой путь для решения подобных проблем. Используя расширенную команду include, вы можете записать, например:

include johns_file.e as john
include bills_file.e as bill
john:x += 1
bill:x += 2

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

Euphoria подталкивает вас к сужению сцены имён. Если бы все имена были автоматически глобальными для всей программы, у вас была бы масса конфликтов имён, особенно в программах, состоящих из файлов, написанных многими разными авторами. Конфликт имён должен вызывать сообщение об ошибке от компилятора, иначе он мог бы вести к очень скрытной ошибке, когда различные части программы встречно и случайно модифицируют одну и ту же переменную, не догадываясь об этом и никак не сигнализируя программисту о творящихся тайных безобразиях. Старайтесь использовать наиболее ограниченную сцену из всех, которые вы можете задать. Делайте переменные частными (только для подпрограммы) везде, где это возможно, а если это невозможно, делайте их местными (только для текущего файла), а не глобальными для целой программы.

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

Объявления констант должны быть вне тела любых подпрограмм. Константы могут быть глобальными или местными (локальными), но не частными.

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

Объявления местных имён на уровне файла, вне тела любых подпрограмм, не должны находиться внутри тела команд циклов (for, while) или тела команды ветвления (if).

Управляющая переменная, используемая в команде цикла for, является особым случаем. Она автоматически объявляется перед началом циклических расчётов, и её сцена ограничена телом команды циклa. Если команда цикла расположена внутри тела подпрограммы, переменная цикла является частной переменной и должна иметь имя, отличающееся от всех других объявленных частных переменных данной подпрограммы (к которым относятся и переменные, объявляемые в списке аргументов). Когда команда цикла находится на уровне файла, вне тела любых подпрограмм, переменная цикла является местной (локальной) переменной и должна иметь имя, отличающееся от всех других уже объявленных местных переменных данного файла. Но вы можете использовать одно и то же имя переменной цикла для различных циклов, если циклы не являются вложенными один в другой. Вам не нужно объявлять тип переменной цикла так, как это делается с другими переменными. Диапазон значений переменной цикла, задаваемый в команде цикла, определяет и все её законные значения, следовательно, любое добавочное задание её типа было бы излишним и поэтому не предусмотрено.

Оглавление книги


Генерация: 0.811. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз