W Cat - Язык программирования Euphoria. Справочное руководство
if equal("APPLE", "ORANGE") then -- ПРАВИЛЬНО
В общем-то, для несколько более полного сравнения рядов имеется ещё и встроенная функция compare() (сравнить):
if compare("APPLE", "ORANGE") = 0 then -- ПРАВИЛЬНО
Вы можете использовать compare() также и для других сравнений:
if compare("APPLE", "ORANGE") < 0 then -- ПРАВИЛЬНО
-- здесь "APPLE" меньше чем "ORANGE",
-- так как длина второго ряда больше (истина, 1)
2.2.5 Индексирование рядов
Единственный элемент ряда может быть отобран путём задания номера элемента ряда (индекса элемента) в квадратных скобках. Номера элементов (индексы) начинаются с 1. Не-целые индексы также допускаются, но при этом округляются вниз до ближайшего целого (отбрасывается дробная часть).
Например, если x содержит {5, 7.2, 9, 0.5, 13}, то x[2] равно 7.2. Предположим, что мы присвоили какое-то другое значение x[2]:
x[2] = {11,22,33}
Тогда x становится равным: {5, {11,22,33}, 9, 0.5, 13}. Теперь, если мы повторим индексирование x[2], то получим {11,22,33}, а если сделаем запрос x[2][3], то результатом будет атом 33. Если вы попытаетесь индексировать ряд числом, которое выходит за пределы диапазона от 1 до числа элементов ряда, вы получите сообщение об ошибке индексирования. Например, x[0], x[-99] или x[6] все вызовут ошибку. То же самое произойдет и для x[1][3], так как x[1] не является рядом в нашем примере. Как такового, предела на число индексов (размерность ряда) не существует, но тогда ряд должен быть достаточно глубоко вложенным. Двумерный массив, так широко распространённый в других языках, может быть легко представлен рядом рядов:
x = {
{5, 6, 7, 8, 9}, -- x[1]
{1, 2, 3, 4, 5}, -- x[2]
{0, 1, 0, 1, 0} -- x[3]
}
где мы записали числа таким образом, чтобы структура ряда проявилась более отчётливо. Выражение в форме x[i][j] даёт доступ к любому элементу.
Но измерения в этом ряде рядов, тем не менее, не вполне симметричны, так как любая "строка" целиком может быть отобрана как x[i], а столь же простого выражения для отбора целой "колонки" не существует. Другие логические структуры, такие как n-мерные массивы, массивы строк, структуры, массивы структур и т.д., могут быть обработаны легко и гибко:
3-D массив:
y = {
{{1,1}, {3,3}, {5,5}},
{{0,0}, {0,1}, {9,1}},
{{-1,9},{1,1}, {2,2}}
}
y[2][3][1] равно 9
Массив строк:
s = {"Hello", "World", "Euphoria", "", "Last One"}
s[3] равно "Euphoria"
s[3][1] равно 'E'Структура:
employee = {
{"Джон","Смит"},
45000,
27,
185.5
}
Чтобы обращаться к "полям" или элементам внутри структуры в хорошем стиле программирования, целесообразно создать набор констант для имён различных полей структуры. Тогда вашу программу будет легко читать. Для примера выше можно было бы иметь:
constant NAME = 1
constant FIRST_NAME = 1, LAST_NAME = 2
constant SALARY = 2
constant AGE = 3
constant WEIGHT = 4
Тогда имя служащего можно получить как employee[NAME], а фамилию - как employee[NAME][LAST_NAME].
Массив структур:
employees = {
{{"John","Smith"}, 45000, 27, 185.5}, -- a[1]
{{"Bill","Jones"}, 57000, 48, 177.2}, -- a[2]
-- .... и так далее.
}
employees[2][SALARY] будет 57000.
Встроенная функция length() выдаёт длину поданного в неё ряда. Следовательно, последний элемент ряда s равен:
s[length(s)]
Имеется короткая форма записи, сокращение, для подобных операций:
s[$]
Аналогично,
s[length(s)-1]
может быть упрощено до:
s[$-1]
Символ $ равен длине ряда. Сокращение $ можно использовать только внутри квадратных скобок. Если ряды вложенные, то есть:
s[$ - t[$-1] + 1]
первый $ относится к длине s, а второй - к длине t (как вы, возможно, и ожидали). Ниже приведён пример, в котором $ может избавить вас от лишней работы, делая ваш код более ясным и, вероятно, даже более быстрым:
longname[$][$] -- последний элемент последнего элемента
Сравните с обычной формой записи той же самой операции:
longname[length(longname)][length(longname[length(longname)])]
Индексирование и функциональные побочные эффекты. Рассмотрим команду присваивания, когда в её левой части выполняется индексирование:
lhs_var[lhs_expr1][lhs_expr2]... = rhs_expr
Здесь все вычисления выражений и любое индексирование производится слева направо. В выражении из правой части команды присваивания или в любом их левых выражений возможно использование вызова функции. Если при вызове функции возникает побочный эффект, приводящий к модификации lhs_var, то теряется определённость, появятся ли эти модификации в lhs_var, когда выполнение команды присваивания будет завершено. Чтобы быть вполне уверенным в том, что ваши ожидания исполнятся именно так, как вы этого хотите, следует выполнять вызов функции в отдельной команде, а не пытаться модифицировать lhs_var двумя различными путями в одной и той же команде. В тех случаях, когда в левой части команды присваивания индексирование отсутствует, вы можете всегда считать, что окончательное значение lhs_var будет равно значению rhs_expr, вне зависимости от любых побочных эффектов, которые могли бы изменить lhs_var.
Структуры данных Euphoria имеют почти бесконечную гибкость. Массивы в других языках вынуждены иметь фиксированное число элементов, и эти элементы должны все быть одного и того же типа. Euphoria снимает оба эти ограничения. Вы можете легко добавить новую структуру в ряд employee (см.выше), или разместить необычайно длинное имя в поле NAME, и Euphoria позаботится обо всех этих изменениях автоматически. Если вы хотите, вы можете поместить множество различных "структур" employee, с различными размерами, все в один ряд.
Программа Euphoria не только легко представляет все обычные структуры данных, но вы можете создавать и новые очень полезные гибкие структуры, которые было бы экстремально трудно определить в другом языке. Прочтите 2.3 Euphoria против других языков.
Имейте в виду, что выражения в общем не могут быть индексированы, индексировать можно только переменные и константы. Например: {5+2,6-1,7*8,8+1}[3] не поддерживается. Нельзя делать и что-либо вроде date()[MONTH]. Вы должны присвоить значение ряда, выдаваемого date(), переменной или константе, а затем индексировать их обычным путём, чтобы получить желаемый результат.
2.2.6 Сечение рядов
Из ряда могут быть выделены несколько последовательных элементов путём задания в квадратных скобках номеров первого и последнего элементов выделяемого участка (отрезка). Например, если x равно {1, 1, 2, 2, 2, 1, 1, 1}, то отрезок x[3..5] будет представлять собой ряд {2, 2, 2}. x[3..3] будет равно ряду {2}. x[3..2] также разрешено, и выдает пустой ряд длины ноль {}. Если y имеет значение: {"fred", "george", "mary"}, то y[1..2] равно {"fred", "george"}.
Мы можем также использовать отрезки для переписывания порций ряда. После команды x[3..5] = {9, 9, 9} x будет равно {1, 1, 9, 9, 9, 1, 1, 1}. С тем же эффектом мы могли бы записать x[3..5] = 9. Предположим y равно {0, "Euphoria", 1, 1}. Тогда y[2][1..4] будет "Euph". Если мы напишем y[2][1..4]="ABCD", то y станет равным {0, "ABCDoria", 1, 1}.
В общем случае имя переменной могут сопровождать 0 или более индексирований за которыми следует 0 или 1 сечение. Только переменные и константы могут быть проиндексированы или рассечены, но не выражения.
В отношении пустых отрезков следует иметь в виду следующие детали. Рассмотрим отрезок s[i..j], где s имеет длину n. Отрезок от i до j, где j = i-1 и i >= 1 создает пустой ряд, даже если i = n+1. Таким образом, 1..0 и n+1..n, и все другие варианты внутри являются законными (пустыми) отрезками. Пустые отрезки весьма полезны во многих алгоритмах. Но отрезок от i до j, где j < i - 1 незаконен, т.е. "вывернутые" отрезки, такие как s[5..3], не разрешены.
С отрезками можно использовать сокращение $, то есть:
s[2..$]
s[5..$-2]
s[$-5..$]
s[$][1..floor($/2)] -- первая половина последнего элемента s
2.2.7 Сцепление рядов и атомов - операция &
Над любыми двумя объектами может быть произведена операция сцепления (конкатенации). Для этого служит оператор & - просто "и" в переводе на русский язык. Результатом операции является ряд, имеющий длину, равную сумме длин сцепленных объектов (здесь атомам как бы приписывается длина 1). То есть:
{1, 2, 3} & 4 -- {1, 2, 3, 4}
4 & 5 -- {4, 5}
{{1, 1}, 2, 3} & {4, 5} -- {{1, 1}, 2, 3, 4, 5}
x = {}
y = {1, 2}
y = y & x -- y всё ещё остается равным {1, 2}
Вы можете удалить элемент i любого ряда s, сцепив отрезки ряда до и после ненужного элемента i:
s = s[1..i-1] & s[i+1..length(s)]