W Cat - Язык программирования Euphoria. Справочное руководство
Иногда, используя библиотеки, разработанные другими программистами, вы будете сталкиваться с возникающими конфликтами имён. Один из авторов библиотек, используемых вами совместно, может дать своей подпрограмме то же самое глобальное имя, которое уже было занято другими авторами. Если у вас имеется исходный код, вы можете просто отредактировать одну из библиотек и исправить ситуацию, но тогда вы должны будете повторять это редактирование снова и снова по мере выхода новых версий используемой вами библиотеки. В 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. Если команда цикла расположена внутри тела подпрограммы, переменная цикла является частной переменной и должна иметь имя, отличающееся от всех других объявленных частных переменных данной подпрограммы (к которым относятся и переменные, объявляемые в списке аргументов). Когда команда цикла находится на уровне файла, вне тела любых подпрограмм, переменная цикла является местной (локальной) переменной и должна иметь имя, отличающееся от всех других уже объявленных местных переменных данного файла. Но вы можете использовать одно и то же имя переменной цикла для различных циклов, если циклы не являются вложенными один в другой. Вам не нужно объявлять тип переменной цикла так, как это делается с другими переменными. Диапазон значений переменной цикла, задаваемый в команде цикла, определяет и все её законные значения, следовательно, любое добавочное задание её типа было бы излишним и поэтому не предусмотрено.
2.4.3 Задание типа переменной
Мы уже видели несколько примеров, касающихся типов переменных, но теперь мы дадим типам более развёрнутое и точное определение.
Объявления переменных как таковые записываются в виде имени типа, сопровождаемого списком имён переменных данного типа, которые мы решили объявить как подлежащие дальнейшему использованию в программе. Например,
object a
global integer x, y, z
procedure fred(sequence q, sequence r)
Типы: object (объект), sequence (ряд), atom (число, атом) и integer (целое) являются предопределёнными. Переменная типа object может принимать любое значение. Те переменные, который объявлены с типом sequence, должны всегда быть рядами. Те переменные, которые объявлены с типом atom, должны всегда быть атомами. А те, которые объявлены с типом integer, должны быть атомами с целочисленной величиной в диапазоне от -1073741824 до +1073741823 включительно. Вы можете выполнять точные целочисленные расчёты с величинами, и выходящими из диапазона integer, вплоть до примерно 15 десятичных знаков, но тогда должны объявлять под них переменные типа atom, а не integer.
Примечание: В списке аргументов процедуры или функции, как это показано, к примеру, для процедуры fred(), имя типа должно сопровождаться единственным именем переменной-аргумента. Примечание о производительности: Вычисления с использованием переменных, объявленных как integer, будут обычно более быстрыми, чем вычисления с переменными, объявленными как atom. Если ваша машина имеет сопроцессор плавающей точки, Euphoria будет использовать его для работы с атомами, которые непредставимы как integer. Если на вашей машине сопроцессор отсутствует, Euphoria будет вызывать подпрограммы арифметики плавающей точки, которые имеются в интерпретаторе ex.exe (или у Windows). Вы можете заставить ex.exe обходить сопроцессор, установив переменную окружения:
SET NO87=1
При этом будут использованы сравнительно медленные встроенные подпрограммы, но здесь может быть и некоторое преимущество, если вы, к примеру, обеспокоены наличием ошибки сопроцессора в некоторых ранних версиях микросхем Pentium. Если предопределённые типы не вполне соответствуют вашей задаче, вы можете создать свои собственные типы. Всё, что нужно сделать для этого - написать функцию с единственным аргументом, но объявить её как type ... end type вместо function ... end function. Например,
type hour(integer x)
return x = 0 and x <= 23
end type
hour h1, h2
h1 = 10 -- ok
h2 = 25 -- ОШИБКА! Программа прерывается с сообщением
Переменным h1 и h2, объявленным с типом hour (час), может быть присвоена только целочисленная величина в диапазоне от 0 до 23 включительно. После каждого присваивания h1 или h2 интерпретатор будет вызывать тип hour(), подавая новую величину. Величина сначала будет проверена на соответствие типу integer (объявлена как "integer x"). Если соответствует, то будет вычисляться выражение, подаваемое в команду return, чтобы проверить значение x (т.е. новую величину h1 или h2). Если hour() выдаёт значение "истина", исполнение программы продолжается. Если hour() выдаёт значение "ложь", программа прерывается с соответствующим диагностическим сообщением.
Тип "hour" может использоваться также для объявления аргументов подпрограммы:
procedure set_time(hour h)
Процедура set_time() может быть вызвана только с подходящей величиной аргумента h, иначе программа будет прервана с сообщением.
Тип переменной будет проверяться после каждого присваивания переменной нового значения (за исключением тех случаев, когда компилятор может предварительно определить, что в проверке нет необходимости, и программа будет немедленно прерываться, если функция типа выдаёт ложь. Типы аргументов подпрограммы проверяются при каждом вызове подпрограммы. Эта проверка гарантирует, что переменная никогда не может иметь величину, не принадлежащую к типу данной переменной.