Продолжается подписка на наши издания! Вы не забыли подписаться?

Основы Cache ObjectScript
Основные элементы Cache ObjectScript

Глава из книги "Постреляционная СУБД Cache,объектно-ориентированная разработка приложений”, В.Кирстнер, М.Ирингер, М.Кюн, Б.Рериг, изд. Бином, М., 2005 "

Переменные

В Cache ObjectScript имеется различие между локальными (существующими лишь в памяти) и глобальными (то есть хранящимися в базе данных) данными. Оба вида данных – локальные и глобальные – могут существовать в виде скалярных или многомерных структур. Cache ObjectScript предоставляет возможность чрезвычайно эффективного прямого доступа (Direct Access) к глобальным данным.

С позиций многопользовательской системы возможна и другая классификация временных и хранимых данных. Временные данные всегда привязаны к одному процессу и ни при каких обстоятельствах не могут обрабатываться другими процессами.

Хранимые данные, напротив, являются многопользовательскими, другими словами (при наличии соотвтествующих прав) они доступны также и для обработки другим процессам. Таким образом, они находятся в распоряжении всей системы, так сказать, глобально, отсюда и их название: глобальные переменные или, кратко, глобалы. Чтобы отличить их от локальных переменных, имена глобалов начинаются с символа «^».

Имена переменных

Общая длина имени локальной или глобальной переменной не ограничена, правда, определяющими являются только первые 31 символ. Первым символом должна быть строчная или прописная буква, либо символ %. Все остальные символы могут представлять собой смесь букв или цифр из 7-битного набора символов ASCII. Знаки препинания, исключая точку, которая может быть использована в любой позиции имени глобальной переменной, кроме первой и последней, запрещены. Имена переменных чувствительны к регистру. Так, locvar отличается от Locvar. Локальные и глобальные переменные могут создаваться командами Set, Read и For. С помощью команды Kill они могут быть уничтожены.

Set Article1 = "Бpюки"
Read "Артикул2 — ", Article2
Kill Article1, Article2

После выполнения команд Set и Read переменные Article1, Article2 имеют определенные значения, после выполнения команды Kill их содержимое удаляется, и переменные Article1 и Article2 более не определены.

Область видимости локальных переменных может определяться программистом разными способами.

В Cache ObjectScript отсутствует декларирование переменных: единственный тип данных – это строка символов переменной длины, то есть все переменные — это переменные типа string. Тем не менее, внутренними средствами системы результат арифметической или логической операции интерпретируется как число или, соответственно, как логическое значение.

Системные, или специальные переменные представляют собой следующую категорию переменных. Внутри Cache ObjectScript они являются предопределенными и могут изменяться программно лишь в редких случаях. Их признаком является символ $. Типичным примером является переменная $Horolog, содержащая внутреннее системное время.

И, наконец, не следует забывать о существовании особого рода внутренних структурированных системных переменных, которые можно себе представить, как смешение описанных выше системных и глобальных переменных. Синтаксически они предваряются двумя символами «^$». Они содержат системную информацию. Например, в структурированной системной переменной ^$Job содержится информация о текущем процессе.

Системные переменные

В таблице 1 представлены важнейшие системные переменные. Если часть имени системной переменной заключена в квадратные скобки, имя может быть сокращено до знака доллара и первой буквы имени переменной. Некоторые, не приведенные здесь, системные переменные встретятся в ходе дальнейшего изложения, где и будут подробно рассмотрены. К ним относятся системная переменная $TLevel в контексте обработки транзакций, а также все системные переменные, относящиеся к обработке ошибок (смотри раздел Обработка ошибок).

Таблица 1. Системные переменные.

Системная переменная Краткое описание
$HALT Если $HALT содержит имя программы, эта программа будет вызвана при выполнении команды Halt.
$H[orolog] $Horolog содержит дату и время в форме 2 счетчиков, отделенных друг от друга запятой. Первый счетчик показывает количество дней, начиная с пятницы, 31 декабря 1840 года (нулевой день), второй счетчик – количество секунд, начиная с полуночи. Обратите внимание также на специальную переменную $ZTimeStamp, аналогичную переменной $Horolog, но показывающую дополнительно еще и миллисекунды.
>Write $Horolog // выводит «57713,36814»
>Write $Piece($Horolog, ", ", 2) // выводит «36815»
>Write +$Horolog  // выводит «57713»
$I[O] $IO содержит имя используемого в текущий момент устройства ввода-вывода.
>Use "TTA3:" Write $I0  // выводит «TTA3:»
$J[ob] $Job содержит положительное целое число, однозначно идентифицирующее каждый текущий процесс в данной системе. $Job не изменяется, пока данный процесс является активным.
>Write $Job  // выводит «1024»
>Set ^temp($Job) = "String"
$K[ey] $Кеу содержит символ или последовательность символов, которым завершилась последняя команда Read. Сравните ее с эквивалентной с функциональной точки зрения переменной $ZB.
>Write $Key  // выводит «<Return>»
$P[rincipal] Подобно $IO, $Principal содержит имя устройства, с которого был запущен текущий процесс.
>Write $Principal  // выводит «/dev/tty05»
$Q[uit] Вызванная в пользовательской функции переменная $Quit всегда имеет значение 1, в противном случае (в подпрограмме) – значение 0.
>Write $Quit «1»
$S[torage] Содержит количество байт, предоставленных для хранения локальных переменных в текущем процессе. Смотри также $ZStorage.
>Write $Storage “15845”
$T[est] $Test содержит значение только что вычисленного тестового условия.
$Test устанавливается при использовании If с аргументом, а также в командах Open, Lock, Read и Job с таймаутом. Безаргументные команды If и Else (также как и постусловие) не меняют значения $Test.
$Test при вызове пользовательских функций и специальных переменных, а также программного блока неявно обрамляется безаргументной командой Do и по окончании вызова вновь устанавливается в старое значение.
>If a = 5 Write $Test  // выводит «1» (если а = 5)
>Open dev::10 Write $Test // выводит «1» (если Open проходит в течение 10 сек.)
$X отражает горизонтальную позицию курсора по отношению к началу строки на устройстве вывода. Каждый выводимый печатный символ увеличивает значение системной переменной $X на 1. Максимальное значение составляет 255 и далее сбрасывается в ноль.
>If $X > 79 Write !
$Y $Y отражает вертикальную позицию курсора по отношению к устройству вывода. Каждый символ перевода строки (ASCII 10) увеличивает, значение $Y на 1 до тех пор, пока, достигнув максимального значения (255), оно снова не сбросится в ноль.
>If $Y > 59 Write #
$ZA Статус последней команды Read на текущем устройстве.
>Write $ZA # 21
$ZB Функционально эквивалентна $Кеу, содержит символ или последовательность символов, считанных последнюю команду Read.
>Write $ZB  // выводит «<Return>»
$ZC[hild] Если текущий процесс Cache, используя команду Job, запустил новый процесс, $ZChild содержит его идентификатор. Значение равно 0, если новый процесс не стартовал.
>Write $ZChild  // выводит «37»
$ZEOF $ZEOF является признаком достижения конца файла после выполнения операции чтения из него. Если был достигнут конец файла, $ZEOF устанавливается в 1.
>If $ZEOF Close file
$ZH[orolog] $ZHorolog содержит время в секундах и миллисекундах со времени старта Cache.
>Write $ZHorolog // выводит «2365.63»
$ZI[O] $ZIO содержит информацию о типе терминального устройства. Если речь идет, например, о связи через Telnet, то $ZIO содержит IP – адрес клиента в форме nnn.nnn.nnn.nnn/port, или, если работает распознавание имен, Name/port где Name — имя клиентской машины.
>Write $ZIO  // выводит «192.9.200.79/1260»
$ZJ[ob] $ZJob содержит число, которое содержит специальную информацию о текущем процессе, представленную в виде битовой строки.
5
$ZM[ode] $ZMode содержит параметры устройства, заданные в последней команде Open или Use.
>Write $ZMode «RY\ISM\»
$ZN[ame] $ZName содержит имя загруженной в текущий момент программы.
>Write $ZName  // выводит «Rec112»
$ZNS[pace] $ZNSpace содержит имя текущей области.
>Write $ZNSpace  // выводит «USER»
$ZP[arent] $ZParent содержит идентификатор процесса, который создал текущий процесс с помощью команды Job. Если он создавался не с использованием команды Job, значение равно 0.
>Write $ZParent  // выводит «0»
$ZPI Содержит математическую константу Pi = 3.141592653589...
>Write $ZPI «3.141592653589793238»
$ZR[eference] $ZReference возвращает полную ссылку на только что использованную глобальную переменную.
>Set ^G(1) = "Hello"
>Write $ZReference  // выводит «^G(1)»
$ZS[torage] $ZStorage содержит (или устанавливает) размер рабочей памяти (в KB), который имеется или должен иметься в распоряжении процесса Cache.
>Write $ZStorage  // выводит «24»
$ZtimeStamp $ZTS $ZtimeStamp, также как и $Horolog, содержит счетчик дней и секунд, последний с сотыми долями секунд.
>Write SZTS  // выводит «57500,11608.52»
$ZTimeZone $ZTZ $ZTimeZone содержит число минут смещения времени для данного часового пояса относительно Гринвича. Если произвести изменение значения $ZTimeZone, то значение $Horolog тоже изменится и будет соответствовать данному часовому поясу.
>Write $ZTZ  // выводит «300»
$ZV[ersion] $ZVersion содержит номер версии используемой в текущий момент времени системы Cache.
>Write $ZVersion  // выводит «Cache for Windows NT (Intel) 5.0»

Операторы и выражения

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

Бинарные операторы подразделяются на группы:

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

Существуют три унарных оператора: ' (NOT), + (плюс) и - (минус). Каждый логический оператор и оператор сравнения с помощью символа НЕ (') может быть превращен в свою логическую противоположность.

При этом действует следующее общее правило:

А '<ор> B эквивалентно '(А <ор> В).

При этом <ор> может быть одним из операторов =, [, <, ], ]], >, &, !, а также ?.

2 '= 3 соответствует '(2 = 3) (ИСТИНА) 
6 '< 10 соответствует '(6 < 10) (ЛОЖЬ)

При этом составной оператор '= можно расшифровать как оператор «не равно», а '< как оператор «не меньше» или «больше или равно».

Обзор операторов

Унарные арифметические операторы ( +, - )

Эти операторы обеспечивают числовую интерпретацию операнда. Оператор «МИНУС» изменяет знак операнда.

Выражение Значение
--13 13
+"12аЬ" 12
+$Horolog 57731

Унарный логический оператор (')

Оператор «НЕ» инвертирует логическое значение следующего выражения. Двукратное применение соответствует простой логической интерпретации выражения.

Выражение Значение
'1 0
'0 1

Бинарные арифметические операторы( +, -, *, /, \, #, ** )

Наряду с четырьмя основными видами вычислений (+, -, *, /) существуют еще и целочисленное деление \, оператор возведения в степень ** (с помощью которого, задавая дробные степени, можно вычислять также и корни чисел), а также остаток от деления #, формально определяемый как:

а # b соответствует a - (b * [a/b]), 

При использовании операторов /, \ и # деление на 0 запрещено.

Пусть а = 5, b = 7, с = 10.

Выражение Значение
а + b 12
а * b – с 25
с / а 2
2 + а * b 49
2 + (а * b) 37
3700 # 3600 100
с # а 0
9.123 \ 1 9
3700 \ 3600 1
2 ** 5 32
9 ** .5 3
16 ** .25 2
4 ** (-2) .0625

Операторы сравнения (<, >)

Прежде чем произвести сравнение, операнды конвертируются в числовые значения. Результатом сравнения является 0 для ЛЖИ или 1 для ИСТИНЫ.

Пусть у = 12, z = 15:

Выражение Значение
y < z 1
z > "16abc" 0

Операторы строкового сравнения (=, [, ], ]])

Оператор сравнения «=» проверяет две строки символов на равенство. Если хотят осуществить проверку на числовое равенство, то прежде необходимо произвести числовую интерпретацию с помощью знака плюс (например, + число1 = + число2).

Оператор содержит «[» определяет, содержится ли правая строка в левой, а оператор «]» определяет, является ли первая строка большей, чем вторая с лексикографической точки зрения, то есть будет ли вторая строка при сортировке идти после первой. Оператор сортировки «]]» является аналогом оператора «]», но, в отличие от него, производит проверку не с лексикографической точки зрения, а интерпретируя значения операндов, например, числа при этом всегда больше любых других строковых значений.

Пусть х = 3, у = "А", z = "3.0"

Выражение Значение
х = "а" 0
x = z 0
"ABC" [ у 1
х ] у 0
у ] х 1
z ] (х = у) 1
2 ]] 19 0

Логические операторы (&, !, &&, ||)

Результатом оператора логическое И (&) является ИСТИНА тогда, когда истинны оба операнда, а оператора ИЛИ (!) — когда по меньшей мере один операнд содержит значение ИСТИНА.

Пусть m = 0, n = 1.

Выражение Значение
(m = 1) & (n = 1) 0
(m = 1) ! (n = 1) 1
'(m = 1) & (n = 1) 1
m = 0 '& (n = 1) 1
m = 0 & 'n '= 1 1

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

В дополнение к приведенным выше логическим операторам, Cache ObjectScript предоставляет два связанных с ними оператора && (AND) и || (OR), которые отличаются от & и ! лишь одной важной особенностью: оба пропускают вычисление правого операнда, если вычисление левого уже дает окончательный результат. Это имеет место, если вычисление левого операнда дает ЛОЖЬ в операции AND или ИСТИНУ в операции OR.

Конкатенация (_)

Действие этой операции заключается в сцеплении двух строк в одну результирующую строку.

Пусть х = "12".

Выражение Значение
"АВ" _ "CD" ABCD
"АВ" _ х АВ12
х_"А"[2 1

Оператор проверки по шаблону

Символ оператора проверки по шаблону — это вопросительный знак. Левый операнд — это строка символов, подлежащая исследованию. Правый операнд — это так называемый «шаблон», состоящий из числа и одного или нескольких символов класса. Результатом проверки по шаблону является ИСТИНА, если операнд точно соответствует образцу, в противном случае — 0. В качестве вводного примера приведем число 348, состоящее из 3 цифр. Тогда результатом проверки по шаблону «348 ? 3N» (348 соответствует образцу «три цифры») будет ИСТИНА.

Основу проверки по шаблону составляет лежащий в основе Cache набор символов, подразделяемый на отдельные классы символов. Cache поддерживает целый ряд различных (а благодаря наличию утилиты поддержки национальных языков cnls.exe также и национальных) наборов символов. Основной принцип проверки по шаблону легко объясним на примере 7-битного набора символов ASCII, причем при распространении на другие классы символов необходимо всегда задаваться вопросом, какому классу символов принадлежит заданный символ.

При этом класс управляющих символов определяется как класс, состоящий из символов ASCII с кодами 0-31, а также 127. Точно также выделяются знаки препинания, цифры и алфавитные символы. Каждый из этих классов получает краткое наименование.

Таблица 2. Классы символов и их значение при проверке по шаблону.

Класс
символов
Наименование Коды ASCII Пример
С Управляющие символы 0-31, 127 $с(7) - Веер
P Знаки препинания 32-47 !, $, %, &, /
N Цифры 48-57 5
U Прописные буквы 65-90 A-Z
L Строчные буквы 92-122 a-z
А Алфавитные символы 65-90, 92-122 A-Z, a-z
Е Все символы 0-127

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

В качестве примера приведем дату в форме дд.мм.гггг (скажем, 29.11.1999), находящуюся в переменной date. Следующая строка кода может служить проверкой ввода даты:

If date ? 2N1P2N1P4N Write "Ввод даты верный "

При этом проверяется соответствие содержимое переменной date шаблону 2N1P2N1P4N. Последний состоит из 5 элементов шаблона, а именно, 2N, 1P, 2N, 1P, 4N. Каждый из элементов шаблона состоит из фактора повторения и класса символов. Элементу шаблона 2N соответствуют ровно две идущих друг за другом цифры, в то время как 1P определяет ровно один знак препинания. Результатом проверки по шаблону является логическое значение, всегда равное 1, если переменная соответствует шаблону, и 0, если это не так.

Введенная дата 310.5.1999 признается в данном случае неверной, так как эта строка символов начинается 3 цифрами, таким образом, третий символ не является знаком препинания, как того требует шаблон.

Вместо общепризнанных знаков препинания может быть точно задан конкретный символ, который необходимо иметь в дате. Чтобы, например, в определенном месте была именно точка, достаточен элемент шаблона 1".", и шаблон для даты можно сформулировать точнее: 2N1"."2N1"."4N.

Кроме того, существует возможность задавать минимально и/или максимально возможное число символов класса. Таблица 3 содержит все допустимые форматы.

Таблица 3. Форматы факторов повторения.

Фактор
повторения
Значение
<Number> Шаблон должен появляться точно <Number> раз.
<Number1>.<Number2> Шаблон должен встречаться как минимум <Number1> раз, однако не более чем <Number2> раз.
<Number>. Шаблон должен появляться как минимум <Number> раз.
. <Number> Шаблон может появляться самое большее <Number> раз.
. Шаблон может появляться сколь угодно часто (или же совсем не появляться).

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

Следующие примеры показывают типичные случаи применения проверки по шаблону:

1U.AP
1.3U1"-"1.2U1" "1.4N
.Е1С.Е

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

Данная форма применения проверки по шаблону может быть с успехом продемонстрирована на примере проверки даты, если следующие форматы даты рассматриваются как допустимые:

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

1.2N1(1"."1.2N1".",1"/"1.2N1"/",1"-"1.2N1"-")4N

При этом идущие друг за другом в скобках шаблоны соответствуют ситуации ИЛИ: должен задаваться либо первый, либо второй, либо третий шаблон. С другими подробностями этого весьма эффективного варианта проверки по шаблону можно ознакомиться в документации по Cache.

Выражения

Обработка выражений играет в Cache ObjectScript совершенно особую роль.

Выражение — это синтаксический элемент Cache ObjectScript, дающий значение. Примером выражения может быть умножение результата, возвращаемого пользовательской функцией, на значение глобальной переменной — например, $$Fun(a) * ^G(1, 2).

Выражение является совокупностью так называемых простейших выражений и унарных либо бинарных операторов. Под простейшим выражением понимается элементарное выражение, которое более невозможно разбить на несколько выражений. Взятые в скобки выражения также представляют собой простейшие выражения.

Таблица 4 описывает встречающиеся в Cache ObjectScript простейшие выражения.

Таблица 4. Простейшие выражения, определенные в Cache ObjectScript.

Простейшее
выражение
Пояснение Пример
<glvn> локальная или глобальная переменная ^G(1, 2)
<svn> системная переменная $Horolog
<function> функция $Length(a)
<exfunc> пользовательская функция $$Х(1)
<exvar> пользовательская переменная-функция $$Н
<numlit> числовой литерал 1.07
<strlit> строковый литерал "abc"
<ssvn> структурированная системная переменная ^$Routine(name, "DAT")
(<expr>) выражение в скобках ($$F1(x1)_$$F2(x2))

Правила, по которым обрабатываются выражения, достаточно просты и недвусмысленны. Они включают в себя три следующих этапа:

  1. Вычисление левого простейшего выражения.
  2. Вычисление правого простейшего выражения и проведение операции.
  3. Движение направо и повторение этапа 2 в случае необходимости. Это означает ни что иное, как отсутствие обычно имеющегося приоритета отдельных операторов. Все бинарные операторы выполняются последовательно слева направо. Следовательно, 3 + 4 * 5 дает в результате 35; путем соответствующего заключения в скобки получают математически корректный результат 3 + (4 * 5) равный 23.

Унарные операторы (это знаки «+» и «-», и логическое отрицание «'») обрабатываются, наоборот, справа налево. Это означает, что сначала вычисляется простейшее выражение (например, функция) и далее выполняется унарная операция.

То, что в первый момент кажется помехой, вместе с неявной интерпретацией типов (см. также следующий раздел) оказывается мощным инструментом, на котором с наслаждением исполняет свою партию опытный программист Cache. Так, например, выражение «j # 4 = 0 + 28» отображает количество дней в феврале. При этом переменная j представляет год между 1901 и 2099. При делении на четыре високосный год делится без остатка, сравнение с 0 дает в результате (логическую) 1, которая суммируется с числом 28.

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

Set¬sum = х + у + z, mue = sum/3

Представление чисел и неявное преобразование типов данных

Динамически типизируемые языки (подобные Cache ObjectScript), следуют соглашениям, с помощью которых автоматически в зависимости от контекста осуществляется преобразование типов данных.

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

Существенным при этом является представление чисел в Cache ObjectScript. Они могут иметь форму целого числа (например, 4661), а также десятичного числа с позицией перед десятичной точкой или без нее (например, 2.1 или .57). Наконец, осталось представление в экспоненциальной форме, где мантисса имеет одну из только что названных форм, а экспонента должна быть положительным или отрицательным целым числом (например, ЗЕ7 или 31.4Е-1). Начиная с версии 4.0 Cache ObjectScript, символ «е» в нижнем регистре также может быть использован для задания экспоненциальной формы числа. Таким образом, константы 1e9 и 1Е9 эквивалентны.

Всем этим числам могут предшествовать ведущие нули (например, 001 или 03Е-3). Перед числом разрешено ставить сколь угодно много знаков плюс и минус. Каждый знак минус изменяет предшествующий знак результата, знаки плюс игнорируются.

При числовой интерпретации строки символов Cache ObjectScript анализируются слева направо. Интерпретация прерывается, как только распознается символ, не укладывающийся в рамки, определенные выше. Если числовая интерпретация невозможна, строке символов присваивается числовое значение 0. Отправным пунктом для следующих примеров является тот факт, что все унарные и бинарные числовые операторы вызывают числовую интерпретацию строки.

Таблица 5. Примеры числовой интерпретации.

Выражение Значение
+"123abc" 123
"314.159E - 2xyz" 3.14159
+"Это число = 1265" 0
+$Horolog 57123
"3 Яблока" + "4 Груши" 7
1 > "Большой" 1 (ИСТИНА)
".3" = "ЗЕ-1" 0 (ЛОЖЬ)
+".3" = +"ЗЕ-1" 1 (ИСТИНА)

Два первых примера очевидны, третий не содержит в начале интерпретируемую в виде числа последовательность символов, цифры, идущие далее, не учитываются. Четвертый пример показывает, каким образом на практике получают часть функции $Horolog, относящуюся ко дню. В шестом примере необходимо знать, что оператор БОЛЬШЕ – это числовой оператор (1 больше 0). Это имеет место и для оператора МЕНЬШЕ, но не для оператора равенства «=»! Как раз это положение вещей и отражено в седьмом примере: ".3" и "ЗЕ-1" – это две совершенно разные строки символов, однако их числовое содержимое одинаково. При проверке на числовое равенство двух переменных сначала должна быть произведена явная числовая интерпретация (последний пример).

В заключение остановимся на логической интерпретации строки символов, являющейся производной от числовой. Если числовая интерпретация строки символов не равна 0, то ее логическая интерпретация — ИСТИНА, то есть 1. И наоборот, если числовая интерпретация 0, то логическая интерпретация данной строки ЛОЖЬ, то есть 0.

Например, выражение "abc" ! "1 Pizza" эквивалентно логическому выражению ЛОЖЬ ИЛИ ИСТИНА, что в итоге представляет собой истинное высказывание.

Команды

С помощью команд в Cache ObjectScript осуществляются различные действия. К примеру, с помощью команды Set переменной присваивается значение, а с помощью команды Do вызывается программа. Cache ObjectScript предоставляет огромное количество команд для самых разнообразных действий.

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

Синтаксис команд и его особенности

Когда пишут «Set ArtNr = 12345678», то речь идет о команде, присваивающей значение переменной ArtNr. Вообще, команды в Cache ObjectScript состоят из командных слов (в нашем примере Set) и относящихся к ним аргументов команды (в примере «ArtNr = 12345678»).

<Командное слово><пробел>[<Аргумент>, <Аргумент>, ...]

В качестве аргумента команды можно задать список отдельных аргументов, отделенных друг от друга запятыми и выполняемых по порядку.

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

Set ArtNr = 12345678, ArtBez = "светлые брюки" 
Do ^Р1(ArtNr, ArtBez), P2(ArtNr)

Имеется целый ряд команд, либо не использующих аргументы вообще, либо применяемых по выбору с аргументами или без аргументов. Важнейшими из них являются: Do, For, If, Else, Quit. Здесь действует правило, что за безаргументной командой должно следовать как минимум 2 пробела (или конец строки), прежде чем может встретиться новая команда.

В Cache ObjectScript можно задавать так называемое командное постусловие. Это логическое выражение, которое определяет, будет ли команда выполняться. Если логическое выражение истинно, то команда выполняется, и наоборот. Логическое выражение следует за командным словом после двоеточия:

<Командное слово><:><логич.выражение><пробел>[<аргумент>, ...]

Например:

Do:Sales > 100000 "SoBu(Sales), ^Warehouse(type)
Set:var = 1 var = 2
0uit:i > 31
Kill:t = 9 var1, var2, var3

Соответствующие постусловия в примере подчеркнуты; каждая команда выполняется, лишь когда постусловие истинно. Это касается команды со всеми ее аргументами. Командные постусловия разрешены для всех команд, за исключением If, Else и For.

Для команд ввода и вывода Open, Use и Close могут задаваться параметры, специфичные для устройства, стоящие в круглых скобках и отделенные от аргумента команды двоеточием.

Open dev:(/CRT:/MARGIN=80)

Скобки могут отсутствовать в том случае, если задается лишь один параметр.

Для четырех особых команд – Read, Open, Lock и Job – возможно задание так называемого времени ожидания (таймаута). Под ним понимается некоторое количество секунд, до истечения которых обработка команды должна завершиться. Если этого не происходит, выполнение команды автоматически прекращается (значение системной переменной $Test устанавливается в ноль).

Read "номер артикула товара: ",ArtNr:10
Open dev::0 Else Write "Устройство недоступно"

Первый пример демонстрирует случай типичного применения таймаута в команде Read. Если в течение 10 секунд ее выполнение не завершится, то она закрывается системой автоматически, и переменная ArtNr содержит введенный до данного момента времени фрагмент текста. Столь же типично применение таймаута в команде Open. Если заданное устройство оказывается доступно программе не сразу (время ожидания равно 0), например, по причине его занятости другим процессом, то открыть его не удается. Для команды Open необходимы два двоеточия, так как первое отделяет специфичные для устройства параметры.

Список важнейших команд

В рамках введения в Cache ObjectScript представим в виде таблицы ряд общих команд, подразделив их на осмысленные группы (команды обеспечения транзакций – это отдельная тема, здесь они отсутствуют). Все команды могут сокращаться до первых букв.

Таблица 6. Важнейшие команды Cache ObjectScript.

Группа команд Типичные представители
Управление последовательностью выполнения программы If, Else, For, Quit, Do, Goto, Break, Xecute
Операции с переменными Set, Merge, Kill, New, Lock
Ввод-вывод Read, Write, Open, Use, Close
Различные другие Job, Hang, Halt, View

Следующая таблица дает краткое описание команд управления последовательностью выполнения программы.

Таблица 7. Команды управления последовательностью выполнения программы.

Команда Краткое описание
If if в форме с аргументом управляет выполнением идущей вслед за ней части программной строки. Она выполняется только тогда, когда проверяемое условие истинно ($Test в таком случае получает значение 1). В обратном случае выполнение продолжается со следующей строки и $Test устанавливается в 0. If в безаргументной форме выполняет остаток строки только если $Test равняется 1.
Вместо этой устаревшей формы команды рекомендуется использовать конструкцию If/Else/Elself.
If t = 1
If age > 30 If sex = "m" 
If Set x = 1
Else Команда Else управляет выполнением идущей вслед за ней части программной строки в зависимости от значения системной переменной $Test, а именно, выполнение имеет место только при $Test равной 0. В противном случае управление передается следующей строке программы. Команда Else не имеет аргументов и не изменяет значения $T.
Вместо этой устаревшей формы команды рекомендуется использовать конструкцию If/Else/Elself.
If a < 1 Do ^P1(t1)
Else Do ^P2(t1)
For Команда For вызывает многократное выполнение выражения, следующего за этой командой. Команда имеется в четырех формах. В форме выражения текущей переменной присваиваются значения из заданного списка. В форме диапазона текущая переменная увеличивается, начиная со своего начального значения, соответственно на значение инкремента, пока не достигнет своего конечного значения. В третьей форме не задается конечное значение, а лишь начальное и инкремент. В безаргументной форме переменная цикла вообще не задается. Эта форма приводит к неограниченному циклу. Такой цикл можно завершить только с помощью команды Quit. Эта команда завершает также любую другую форму цикла For. Вместо этой устаревшей формы команды For рекомендуется использовать новую конструкцию For (см. ниже).
For j = -9, 5, 7, 36, -100 
For i = 1:1:10 
For k = "A", "B", 1:2:11
For l = 1:1
For
Quit Quit завершает текущий цикл For, а также части программ, вызванные с помощью Do или Xecute, то есть программные блоки. В этих формах Quit является безаргументной. Пользовательские функции завершаются командой Quit с аргументом.
Quit 
Quit:t = 10 
Quit a * b
Do Когда команда Do используется с аргументами, одна за другой вызываются локальные подпрограммы или глобальные программы. Если метка отсутствует, программа выполняется с первой строки. Если перед именем глобальной программы указана метка, то выполнение ее начинается с этой метки. После выхода из программы обрабатывается следующий аргумент команды Do, а после их исчерпания – следующая команда после Do. После имени программы может быть задан список фактических параметров. В качестве фактических параметров используются произвольные выражения, кроме того, возможна передача параметров по ссылке. Значения фактических параметров присваиваются формальным параметрам в соответствии с порядком их следования.
Do LoPro, ^Rl(lv, lv1) 
Do ^Programm(a1, .a2)
o:A = 1 PROG:T = 1
Do @nam^@b 
Do ^Р1:С1
Goto Команда Goto изменяет последовательность выполнения программы, «безвозвратно» передавая управление либо строке той же самой программы, либо строке другой программы. На всю команду, как и на каждый из ее аргументов, может быть наложено постусловие.
Goto loclabel
Goto:t A:s = 1, B:s = 2 
Goto L1:C1, L2:C2
Xecute Команда Xecute обеспечивает выполнение строки символов в виде однострочной подпрограммы (без метки). Допускается вложенная конструкция Xecute. На выполнение всей команды, как и каждого ее отдельно взятого аргумента, может быть наложено постусловие.
Xecute а, ^В 
Xecute "S x = 1" 
Xecute:t["a" t(i, 2):true 
Xecute @a_"X @b"
Break Команда Break обеспечивает стандартизованный доступ к средствам отладки. Break без аргумента устанавливает точку останова и приостанавливает выполнение программы. Рекомендуется в этих целях применять команду ZBreak. Имеется несколько вариантов аргумента команды Break. Break 1 дает возможность с помощью <ctrl - c> вызвать прерывание программы, тогда как Break 0 эту возможность исключает. Прерывание программы может быть вызвано также автоматически при определенных условиях, например, после каждого выполнения команды Break "S" (s означает "single step", то есть пошаговое выполнение). Используются и некоторые другие аргументы.
Break 
Break 1 
Break "S"

Далее рассмотрены команды, изменяющие значение или состояние переменных.

Таблица 8. Команды, ориентированные на переменные

Команда Краткое описание
Set Команда Set предназначена для присваивания значений переменным. Присваивание значения нескольким переменным осуществляется путем заключения их в скобки. Если в левой части выражения используются индексы, то выражение справа от знака равенства всегда вычисляется первым. Если необходимо присвоить значение части строки, применяют Set $Piece или Set $Extract.
Set x = 5, n(1) = 4 
Set ^FILE = 3 
Set:a > 0 (i, j, k) = 1 
Set @a = @b + 1 
Set $Piece(v, "*", 3) = "A" 
Merge Merge обеспечивает копирование целых поддеревьев индексированных переменных друг в друга, неважно, определены ли они как локальные или как глобальные.
Merge a = b 
Merge var (1) = ^G(1, 2) 
Kill Kill удаляет локальные или глобальные переменные, заданные в списке аргументов. Kill без аргумента удаляет все локальные переменные, в то время как исключающая команда Kill выполняет действие над всеми локальными переменными программы, за исключением тех неиндексированных переменных, имена которых перечислены в скобках. Узел индексированной переменной удаляется вместе со всеми потомками, если таковые существуют. Глобальные переменные и поддеревья многомерных переменных удаляются только с помощью формы Kill с аргументами.
Kill 
Kill а, b, ^С 
Kill a(1, 3) 
Kill (v1, v2, v3)
Kill:bed p1, p2, @var
New Команда New упрятывает локальные переменные, заданные в ее списке аргументов. Ранее определенные локальные переменные с таким же именем становятся неопределенными. Если приведенной в аргументе команды New переменной присваивается значение, оно остается досягаемым вплоть до завершения текущей программы командой Quit. Перед выходом из программы автоматически проводится Kill этих переменных, и определенные ранее значения вновь становятся видимыми. Безаргументная форма New упрятывает все локальные переменные, тогда как исключающая New распространяется на все локальные переменные, кроме тех, имена которых перечислены в скобках. Команда New оперирует только с неиндексированными переменными, однако ее действие распространяется как на заданную переменную, так и на всех ее (индексированных) потомков.
New 
New a, b 
New(x1, x2) 
Lock Lock используется в основном для блокировки глобальных переменных с тем, чтобы временно объявить их собственностью данного процесса Cache. Имеется четыре варианта команды Lock. Lock без аргумента используется для снятия всех блокировок. Lock с аргументом без знака плюс или минус сначала снимает все блокировки и далее блокирует заданные в аргументе переменные. При этом аргумент – это либо имя переменной, либо заключенный в скобки список имен переменных. Наконец, имеется еще один вариант команды Lock – со знаком плюс перед аргументом, запрашивающий дополнительную блокировку заданных в аргументе переменных, и Lock со знаком минус перед аргументом, избирательно снимающий блокировки. Две последние формы работают инкрементально, что означает: если та же самая переменная v многократно блокируется командой Lock + v, то ровно такое же число раз она должна разблокироваться с помощью Lock - v, прежде чем она станет доступной для блокировки другими процессами. Блокировка узла многомерной переменной вызывает блокировку всех ее потомков. Соседи при этом не затрагиваются. В команде может быть задано время ожидания, а при использовании инкрементальной формы команды его рекомендуется задавать всегда.
Lock 
Lock (a, ^G) 
Lock ^А(1, 2) 
Lock (b, ^Н) : 10 
Lock +^А, -^РЕR(name) 
Lock +(^Р1, ^Р2) 

Следующие команды служат для ввода-вывода на терминалы и другие периферийные устройства. Open, Use и Close представляют собой команды, зависящие от платформы.

Таблица 9. Команды, специфичные для устройства.

Команда Краткое описание
Read Read присваивает локальным и глобальным переменным значения, которые считываются с устройства ввода. Символ звездочка * перед именем переменной означает, что читается ровно один символ, причем заданная переменная получает целочисленное значение, равное коду ASCII этого символа. Возможно задание ограничения длины ввода, оно отделяется от имени переменной символом номера. Точно так же может быть задано и время ожидания для ограничения времени ввода, оно начинается с двоеточия.
Read x, ^G1(ind)
Read "Введите имя пользователя: ", username 
Read * z 
Read:$Data (g) !, "Дата рождения? ", date # 10 
Read @a:10 
Write Команда Write служит для вывода данных на терминал или на указанное пользователем устройство. Символ * сигнализирует о выводе ASCII-эквивалента заданного кода. Контроль формата возможен с помощью #, !, ?, причем # осуществляет переход к новой странице, ! переход к новой строке, а ? – вставку табуляции в некоторую позицию текущей строки.
Write "HELLO" 
Write #!?10, *7
Write: 't a, b, !!, c + t / 5_s 
Write @a, @@v
Open Команда Open служит для открытия устройства или файла. Она резервирует устройство для данной программы до тех пор, пока для этого устройства не будет выполнена команда Close. Можно задать параметры открытия, которые отделяются от имени устройства двоеточием. Они состоят из отдельного выражения или заключенного в скобки списка выражений. После следующего двоеточия может быть задано ограничения времени, отведенного на попытку открытия.
Open device
Open 3, prnt::time 
Open: 'closed @band 
Open term: (Param) :20 
Use Use используется вместе с командой Open для того, чтобы устройство стало текущим устройством ввода-вывода. Возможно задание параметров устройства, отделяемых от имени устройства двоеточием и при необходимости помещаемых в скобки.
Use device 
Use:status = "OPEN" ger 
Use 3: (parameter) 
Use @print 
Close Освобождает все зарезервированные, заданные в виде аргумента устройства. За аргументом могут следовать специфичные для устройства параметры.
Close "DEV", 3 
Close:bed > 3 line 
Close tty:(/DELETE) 

Следующая группа включает в себя четыре команды, имеющие совершенно разные области применения.

Таблица 10. Другие команды.

Команда Краткое описание
Job Job запускает один или несколько фоновых процессов Cache из текущей программы. В качестве аргумента задается точка входа локальной или глобальной подпрограммы. Передача параметров в фоновый процесс возможна через список выражений, заключенный в скобки. После двоеточия могут быть заданы параметры процесса. Это может быть либо отдельное выражение, либо заключенный в скобки список выражений. Следующим двоеточием отделяется время ожидания, если оно необходимо.
Job ^А 
Job В, А1^РROG 
Job:g = 1 J1::10 
Job @var: (Parameter) 
Job ^P1(4, x1, $E(name)) 
Hang Команда Hang приостанавливает выполнение текущего процесса на число секунд, заданное ее аргументом. Если аргумент отрицателен либо 0, то команда не имеет никакого эффекта.
Hang 10 
Hang:t = 1 b / 4 
Hang @i 
Halt По команде Halt завершается текущий процесс. Прежде всего снимаются все сделанные им блокировки (неявно выполняется Lock без аргумента) и закрываются (неявной командой Close) все устройства, зарезервированные этим процессом. Halt не имеет аргумента, поэтому ее краткую форму несложно отличить от команды H[ang].
Halt 
Halt: Condition 
View Команда открывает доступ к памяти системы и прямой доступ к диску, то есть может быть прочитано и изменено содержимое памяти и дисковых блоков. Использование этой команды является прерогативой опытного программиста.
View 6 
View 0:ADDR:"WXYZ" 

Обзор Z-команд

В данном разделе приведено описание группы команд Cache ObjectScript, известных как Z-команды, поскольку их имена начинаются с буквы Z. Для начала сгруппируем эти команды в единой таблице.

Таблица 11. Список Z-команд.

Группа команд Краткое описание Команды
Команды редактирования Команды изменения текста программ в режиме редактирования ZI [nsert], ZL[oad], ZP[rint], ZR[emove], ZS[ave], ZW[rite]
Обработка ошибок Для назначения точек останова и выдачи сообщений об ошибках ZB[reak], ZQ[uit], ZT[rap], ZSYNC
Системные команды Для изменения некоторых параметров системы, например, для смены текущей области ZK[ill], ZN[space]

Что касается команд редактирования, то для программиста с опытом работы в Cache они (непосредственно в режиме программирования, без вызова Cache Studio) позволяют:

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

Группа команд, касающаяся обработки ошибок, включает в себя еще три команды, которые мы обсудим позже.

ZKill — это расширение обычной команды Kill. Zkill позволяет удалять индексированную переменную, не затрагивая потомков, то есть индексы на более глубоком уровне, как это имеет место в команде Kill.

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

Оператор косвенности @

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

Косвенное имя

Предположим, переменная v1 содержит в качестве значения имя локальной переменной, например, «v1 = "locvar"». Тип данных значения v1 очевидно представляет собой строку.

Разумеется, присваивание «Set "locvar" = 4» приведет к сообщению об ошибке, так как команда Set ожидает имя переменной, а не строку символов. Однако имея оператор косвенности "@", программист может преобразовать тип данных в имя: «Set @v1 = 4» присваивает переменной locvar значение 4. Эта форма косвенности называется косвенным именем.

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

Set pname = "^Prog1" Do @pname

Здесь вызывается программа ^Prog1.

Косвенный аргумент

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

Set isetarg = "x = 1", @isetarg

Переменная isetarg содержит синтаксически корректный аргумент команды Set в виде строки, которая обрабатывается оператором косвенности. Отчетливо видно отличие от косвенного имени, ведь «"х = 1"» — не разрешенное имя. Разумеется, во многих командах (Read, Write, Kill, New — их далеко не полный перечень) одиночный аргумент также может быть именем. В этом случае обе формы косвенности неотличимы друг от друга.

А вот несколько примеров, в которых обе эти формы косвенности имеют различия:

Set ikill = "(e, f, g)" Kill @kill 
Set inew = "(a, b, c)" New @inew

Индексная косвенность

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

Пример иллюстрирует основную идею:

>Set x(2, 5, 3) = "IndInd" Set feld = "x(2, 5)", d1 = 3
>Write @feld@(d1)
IndInd

Мы видим расширение ссылки х (2, 5) индексом третьего уровня со значением 3.

Косвенный шаблон

При сравнении с шаблоном имеется возможность задать полный шаблон косвенно:

Set lvmuster = "1.3N" If eingabe '? @lvmuster Do Error

Встроенные функции

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

В этой связи следует назвать также функции, определенные пользователем, или, для краткости, пользовательские функции, создаваемые пользователем-разработчиком самостоятельно (см. ниже).

Характеристики встроенных функций

В Cache ObjectScript имена всех встроенных функций начинаются со знака доллара. Аргументы функции заключаются в скобки и отделяются друг от друга запятыми. В общем случае вызов функции имеет следующий вид:

$Function(Argument1, Argument2, ...)

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

>Write $Extract("Sommersmog", 7, 10)
smog
>Set d1 = 2 * $Length("Sommersmog") Write d1
20
>Set zk = "Becнa, лето, осень, зима"
>Write $Extract(zk, 7, $Length(zk))
лето, осень, зима

Первый пример показывает извлечение подстроки из строки символов с использованием функции $Extract. Второй пример напоминает о том, что функция может представлять собой часть выражения. Третий пример поясняет, что аргументы функций сами могут быть функциями.

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

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

Встречаются следующие варианты выражений:

Таблица 12. Варианты выражений Cache ObjectScript.

Аргумент Выражение
<expr> произвольное выражение
<int expr> выражение, интерпретируемое как целое число
<num expr> выражение, интерпретируемое как число
<log expr> выражение, интерпретируемое логически

При этом преобразование происходит автоматически. Если в качестве аргумента функции ожидается <int expr>, а в действительности имеется произвольное выражение (например, «7 ** 2 * 3.14159»), то сначала вычисляется это выражение (дает в результате 153.93791), из него получается целочисленное значение 153, которое далее используется для вычисления функции. Пример поясняет эту ситуацию:

>Write $Extract ("Распорядок дня", 2.5, 3.5)
ас

Соответствующие позиции, начиная с которой и вплоть до которой осуществляется выделение, не являются целыми числами, однако автоматически преобразуются путем целочисленного деления на единицу в целые числа 2 и 3.

Классификация встроенных функций

Следующая таблица дает список определенных в Cache ObjectScript функций, на которых более подробно мы остановимся в последующих разделах.

Таблица 13. Обзор классов встроенных функций Cache ObjectScript.

Класс функций Типичные
представители
Общие функции $Ascii, $CASE, $Char, $Random, $Select, $Stack, $Text, $View
Операции с переменными и базой данных $Data, $Get, $Order, $Name, $Query, $Qsubscript, $Qlength, $Sortbegin, $Sortend
Обработка строк $Extract, $Find, $Length, $Piece, $Reverse, $Translate
Форматирование чисел $FNumber, $Justify, $Inumber, $NUMBER
Обработка списков $List, $ListBuild, $ListData, $ListFind, $ListGet, $ListLength
Обработка транзакций $Increment
Математические функции $ZABS, $ZEXP, $ZLN, $ZSIN, и т.д.
Дата, время $ZDate, $ZDateTime, $ZdateH, $ZTime, $ZtimeH
Обработка битовых строк $BIT, $BITCOUNT, $BITFIND, $BITLOGIC, $ZBOOLEAN, $Zcyc
Общие функции $ISObject, $ZF, $ZHex, $ZISWide, $ZLAscii, $ZLChar, $ZName, $ZSEArch, $ZSEEK, $ZWAscii, $ZWBPack, $ZWBUnpack, $ZWChar, $ZWPack, $ZWUnpack
Строковые функции $ZCONVert, $ZSTRIP, $ZPosition, $ZWidth, $ZZENKAKU
Служебные функции $ZUtil(n) – различные служебные функции, определенные для многих целочисленных n, частично зависимы от платформы

Обзор функций

Функции можно разделить на шесть групп:

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

Таблица 14. Наиболее важные общие функции Cache ObjectScript.

Функция Краткое описание
$A[scii] $A[scii] (<expr>)
$A[scii] (<expr>, <int expr>)$Ascii выбирает из строки (первый аргумент) символ и возвращает код ASCII этого символа. Второй аргумент задает позицию символа в строке. Если он отсутствует, то берется первый символ строки. Если строка символов является пустой строкой, либо второй аргумент меньше единицы или больше, чем длина строки символов, $Ascii выдает значение -1.
>Write $Ascii("A")
65
>Write $Ascii("ABC", 3)
67
>Write $Ascii("")
-1
$CASE $CASE (<expr>, <lit>:<expr> [, ...][, : default] )
$CASE(<expr>, <lit>:<name>[, ...][, : default] )
В первом случае сначала вычисляется первое выражение. Следующая пара <lit>:<expr> состоит из константы (числовой или строковой) с последующим выражением. Если константа соответствует значению первого выражения, то следующее за ним выражение вычисляется и используется в качестве значения функции. Если ни одна константа не соответствует значению первого выражения, используется значение по умолчанию, если, конечно, оно существует. В противном случае возникает ошибка.Если $CASE используется в качестве аргумента команд do или goto, тогда, как показано во втором примере, вместо выражения ожидается имя программы, управление которой будет передано при выполнении условия.
>Write $CASE(A, 1:"One", 2:"Two", 3:"Three", :"something else") 
>Goto $CASE (Input, "*":End, ^Process (Input)) 
$C[har] $C[har] (<int expr>[, <int expr>, ... ])
$Char является обратной по отношению к функции $Ascii и переводит число в соответствующий символ ASCII. Отрицательные аргументы допустимы и порождают пустую строку. Базисом является соответствующий основной набор символов. См. также $ZLChar и $ZWChar,
>Write $Char(65, 66)
AB 
>Write $Char(-1) 
(пустая строка) 
$R[andom] $R[andom] (<int expr>)
Если аргумент функции $Random равняется n, то функция возвращает целое случайное число в диапазоне от 0 до n-1.
>Write $Random(10)
5
$S[elect] $S [elect] (<log expr>:<expr>[, <log expr>:<expr>] ...)
Каждый аргумент функции $Select – это упорядоченная пара, состоящая из логического выражения и произвольного выражения, отделенных друг от друга двоеточием. Интерпретация аргумента производится слева направо до тех пор, пока не встретится истинное выражение. Функция $select возвращает значение выражения справа от двоеточия. Как минимум одно логическое выражение должно быть истинным, иначе возникает ошибка.
>Set a = 1 
>Write $Select (a = 1:5, a > 1:0) 
5 
>Write $S (a = 2:5, 1:0) 
0 
>Set min = $S(s < t:s, 1:t) 
$T[ext] $T[ext] (+ <int expr> [^routine])
$T[ext] (метка строки [^имя программы])
$Text возвращает текст строки программы – разумеется при условии, что та имеется в исходном коде (если строка отсутствует в исходном коде, $Text выдает пустую строку; если же отсутствует весь исходный код, то функция возвращает лишь содержимое строк комментария, начинающихся с двух точек с запятой). В первой форме $Text ссылается на относительный номер строки (например, +3 для третьей строки). Если это число равно 0, возвращается имя программы. В следующем примере показана вторая форма, когда задается имеющаяся в программе метка строки, которая далее (с меткой) и возвращается в качестве результата. Если имя программы отсутствует, то метка ищется в загруженной программе.
>Write $Text( +3) 
Read "Eingabe: ", x 
>Write $Text( +0) 
P1Spec
>Write $Text(Label)
Label Set a = 1, b = 2
$V[iew] $V[iew] (<expr>[, Mode, <num expr>] )
Функция позволяет читать содержимое оперативной памяти и обычно используется в случае возникновения ошибки для получения внутрисистемной информации.

Далее в виде таблицы следуют функции Cache ObjectScript, которые служат для обработки строк.

Функция Краткое описание
$E[xtract] $E[xtract] (<expr>)
$E [xtract] (<expr>, <int expr>)
$E[xtract] (<expr>, <int expr>, <int expr>)
$Extract возвращает подстроку первого аргумента функции, начало и конец которой определены 2 и 3 аргументом. Если третий аргумент не задан, то возвращается один символ, положение которого в строке задано вторым аргументом. Если второй аргумент также не задан, функция $Extract возвращает первый символ строки символов.
Если второй аргумент больше, чем третий или больше, чем длина строки, заданной в первом аргументе, $Extract возвращает пустую строку. Если второй аргумент меньше или равен 1, то функция $Extract возвращает все символы от начала строки до позиции, заданной третьим аргументом. Если он меньше единицы, возвращается пустая строка. Если третий аргумент больше, чем длина строки символов, $Extract возвращает все символы до конца строки.
>Write $Extract ("ABC")            // выводит «A» 
>Write $Extract("XYZ", $L("XYZ"))  // выводит «Z» 
>Write $Extract("AABB", 2, 3)      // выводит «AB» 
>Write $Extract( "лето", 3, 255)   // выводит «тo»
>Write $Extract ("abc", 5)         // выводит пустую строку 
$F[ind] $F[ind] (<expr>, <expr>)
$F[ind] (<expr>, <expr>, <int expr>)
$Find выполняет поиск заданной в виде второго аргумента подстроки в первом аргументе. Поиск начинается с позиции, которая была задана третьим аргументом. Если третий аргумент отсутствует, то поиск ведется с начала первого аргумента.
$Find возвращает позицию первого символа после найденной подстроки. Если искомая строка не найдена, значение функции $Find равно 0. Если в качестве второго аргумента передается пустая строка символов, значение функции всегда равняется третьему аргументу, или если тот не был задан, единице.
>Write $ Find("ABC", "A")       // выводит 2 
>Write $Find("XYZ", "T")        // выводит 0 
>Write $Find("ABABAB", "AB", 3) // выводит 5 
$J[ustify] $J[ustify] (<expr>, <int expr>)
$J[ustify] (<num expr>, <int expr>, <int expr>)
Функция $Justify осуществляет выравнивание по правому краю поля данных путем добавление пробельных символов в начало строки, а также простое форматирование чисел. Второй параметр определяет длину вывода. Если входные данные превосходят заданную длину вывода, они возвращаются без изменений. Третий аргумент – если таковой имеется – задает форматирование числовых элементов данных и вызывает числовую интерпретацию первого аргумента. Задается число позиций после десятичной точки, которое должно получиться путем округления или добавления нулей. Если третий аргумент равен нулю, то не выводятся ни позиции после запятой, ни десятичная точка. Значения больше -1, но меньше 1 представляются с помощью 0 перед десятичной точкой.
>Write $Justify(12, 3) 
12 
>Write $Justify("Text", 10) 
      Text
>Write $Justify(12, 3, 2) 
12.00 
>Write $Justify(3.14, 1, 0) 
3 
>Write $Justify(0.414, 6, 3) 
0.414 
$L[ength] $L[ength] (<expr>)
$L[ength] (<expr>, <expr>)
Функция $Length вычисляет длину строки символов, то есть число символов в этой строке. Длина пустой строки равна 0. Задание строки символов в качестве второго аргумента возвращает увеличенное на единицу количество ее вхождений в первый аргумент. Таким образом подсчитывается число полей, которые разделены этой подстрокой символов. Если второй аргумент – пустая строка, то $Length возвращает значение 0.
>Write $Length("ABCD") 
4 
>Write $Length("") 
0 
>Write $Length ("AB/CD/EF", "/") 
3 
$P[iece] $P[iece] (<expr>, <expr>)
$P[iece] (<expr>, <expr>, <int expr>)
$P[iece] (<expr>, <expr>, <int expr>, <int expr>)
$Piece рассматривает передаваемую в виде первого аргумента строку символов как последовательность полей, отделенных друг от друга передаваемой вторым аргументом строкой символов – разделителем. Она возвращает в форме с двумя аргументами первое поле, в форме с тремя аргументами заданное третьим аргументом поле и в форме с четырьмя аргументами поля в области от аргумента три до аргумента четыре.
Если разделитель в строке символов отсутствует, $Piece возвращает всю строку символов для случая, если третий аргумент равен 1 или отсутствует вообще. В противном случае возвращается пустая строка. Пустая строка в качестве разделителя всегда ведет к результату в виде пустой строки. Если третий аргумент меньше единицы или четвертый аргумент превышает число полей в первом аргументе, осуществляется выделение с первого и соответственно до последнего поля. Если четвертый аргумент меньше третьего либо меньше 1, или же третий аргумент превосходит число полей, то результатом функции $Piece будет пустая строка.
>Set v = "ABC/XYZ/123"
>Write $Piece(v, "/") 
ABC 
>Write $Piece(v, "/", 2) 
XYZ 
>Write $Piece(v, "/", 2, 3) 
XYZ/123 
>Set $P(v, "/", 2) = "***" Write v 
ABC/***/123 
$R[everse] $R[everse] (<expr>)
Функция $Reverse имеет одно единственное назначение – расположить символы в строке в обратном порядке.
>Write $Reverse("Rail")
liaR 
$TR[anslate] $TR[anslate] (<expr>, <expr>)
$TR[anslate] (<expr>, <expr>, <expr>)
Функция $Translate преобразует символы заданной в первом аргументе строки в соответствии с заданными во втором и третьем аргументах правилами замены. В трехаргументной форме для каждого символа первого аргумента устанавливается, встречается ли он во втором аргументе и, если встречается, то, начиная с какой позиции. Если это имеет место, то он заменяется символом, который находится в той же позиции в третьем аргументе. Если длина второго аргумента меньше чем третьего, то лишние символы второго аргумента, не имеющие соответствия в третьем аргументе, удаляются. То же самое происходит, если задаются лишь два аргумента.
>Set u = "EPUR", l = "epur"
>Write $TR("UPPER", u, l) 
upper 
>Write $TR("train station", "aeiou") 
trn sttn

Таблица 15. Строковые функции.

Далее, как мы видим из таблицы 13, в Cache имеется класс функций $LIst для создания и управления списками. Функция $Increment связана с обработкой транзакций. $INumber — функция, родственная $Fnumber, и применение ее весьма ограничено.

Обзор Z-функций

Ввиду того, что количество чрезвычайно важных Z-функций весьма велико, мы ограничимся лишь их кратким описанием.

Математические Z-функции

Существует традиционный для общих систем программирования набор математических функций. К ним относятся:

Представление даты и времени

Основу внутреннего представления даты и времени составляет специальная переменная $Horolog, состоящая из счетчика дней и счетчика секунд, отделенных друг от друга запятой. Некоторые из функций дополнительно ссылаются на специальную переменную $ZTimeStamp, счетчик секунд которой расширен на доли секунд и которая имеет такой же формат, как $Horolog.

Первая из рассматриваемых в данном разделе функций — это $ZDate, кратко $ZD. Здесь мы покажем лишь принцип ее действия и наиболее частые случаи применения.

>Write $ZDate(60000) 
04/10/2005

В этой простейшей форме передается аргумент, интерпретируемый как $Ноrоlоg-формат. Показ даты осуществляется в американском формате ММ/ДД/ГГГГ с косой чертой в качестве разделителя.

В качестве второго аргумента может быть задано число, интерпретируемое как параметр формата.

2 аргумент Формат данных Пример Замечания
0 ДД Ммм [ГГ]ГГ 10 Apr 2005
1 ММ/ДД/[ГГ]ГГ 04/10/2005
2 ДД Ммм [ГГ]ГГ 10 Apr 2005
3 ГГГГ-ММ-ДД 2005-04-10 ODBC-формат
4 ДД/ММ/[ГГ]ГГ 10/04/2005 Европейский формат
5 Ммм Д, [ГГ]ГГ Apr 10, 2005
6 Ммм Д [ГГ]ГГ Apr 10 2005
7 Ммм ДД [ГГ]ГГ Apr102005
8 ГГГГММДД 20050410 Цифровой формат
9 Месяц Д, [ГГ]ГГ April10, 2005

Таблица 16. Выбор возможных форматов с помощью второго аргумента функции $ZDate.

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

>Write $ZDate(60000, 2, " января февраля марта ... декабря") 
10 апреля 2005

В качестве третьего аргумента можно задать список месяцев на любом языке.

$ZDateH (кратко $ZDH) — это обратная функция по отношению к $ZDate. Она возвращает счетчик дней в формате $Horolog для заданной в одном из выше описанных форматов даты.

>Write $ZDateH("4/10/2005")
60000

О других имеющихся в Cache функциях преобразования времени и даты мы лишь упомянем.

Функция Краткая
форма
Краткое описание
$ZDateTime $ZDT подобна функции $ZDate, но с заданием времени в различных форматах
>Write $ZDT($H) 
09/04/1998 10:13:19
$ZDateTimeH $ZDTH аналогична функции $ZDateH, однако создается счетчик секунд в формате $Horolog
>Write $ZDTH("Jun! " 13, 1997 15:19 ! ":23.539", 5) 
57142,55163.539
$ZTime $ZT создает из счетчика секунд в формате $Horolog время в различных форматах на выбор
>Write $ZT(3600) 
01:00:00
$ZTimeH $ZTH из времени создает счетчик секунд в формате $Horolog
>Write $ZTH("02:0!"0:00")
7200

Таблица 17. Функции преобразования времени и даты.

Функции работы с битовыми строками

Битовые операции выполняются с помощью четырех функций: $ВIТ, $BITCOUNT, $BITFIND, и $BITLOGIC. При этом битовая строка – это последовательность состояний «да/нет» (символически изображается в виде последовательности единиц и нулей), например, (0, 1, 0, 0, 1, 1, 1, 0).

Функция $BIT создает битовую строку или устанавливает значение бита в определенной позиции. Двухаргументный вариант $BIT(bitstring, position) извлекает значение бита в позиции, заданной position. Трехаргументный вариант $BIT(bitstring, position, bitvalue) возвращает текущее значение бита, заданного position, и устанавливает его в новое значение, заданное bitvalue.

Функция $BIT также может стоять слева от знака равенства. Этот вариант может быть использован для создания битовой строки или изменения отдельного бита в определенной позиции.

Set а = ""
Set $ВIТ(а, 4) = 1

Здесь переменная инициализируется пустой строкой и затем четвертый бит устанавливается в 1. После этого значение битовой строки будет [0, 0, 0, 1].

Функция $BITCOUNT также существует в двух формах. В форме с одним аргументом $BITCOUNT(bitstring) она возвращает число битов в битовой строке. Если в качестве второго аргумента задано битовое значение (0 или 1), подсчитывается число бит заданного значения.

Третья функция работы с битовыми строками, $BITFIND, ищет заданное значение бита и возвращает его позицию в строке. Например, если а = [0, 0, 1, 1, 0], тогда $BITFIND(a, 1) вернет число 3, поскольку бит со значением 1 первый раз встречается в третьей позиции. Добавление третьего аргумента задает позицию, начиная с которой необходимо начинать поиск. В предыдущем примере $BITFIND (а, 0, 3) вернет значение 5, поскольку бит со значением 0 встречается снова только на 5 позиции.

Функция $BITLOGIC выполняет побитовые логические операции с битовой строкой (таблица 18).

Оператор Символ оператора
И (AND) &
ИЛИ (OR) I
исключающее ИЛИ ^
НЕ (NOT) ~

Таблица 18.

Общая форма функции $BITLOGIC:

$BITLOGIC(bitstring_expression[, length])

Здесь bitstring_expression представляет собой битовое выражение, составленное с помощью операторов, представленных в таблице 18. Таким образом, выражение может состоять либо из последовательности операторов И и ИЛИ (например, «А & В | С»), либо из одного оператора НЕ (например, «~А»). В этом случае в результате получается строка бит, содержащая инвертированные значения бит строки А. В первом варианте можно использовать скобки для задания последовательности операций, например, «(А & В) | (В & С)».

Второй аргумент, length, задает длину результирующей битовой строки.

Допустим, битовые строки А и В представлены следующим образом:

А = [1, 1], В = [0, 1]

Тогда:

Set C = $BITLOGIC(~B)    // С будет равно [1, 0] 
Set C = $BITLOGIC(A & B) // С будет равно [0, 1] 
Set C = $BITLOGIC(A | B) // С будет равно [1, 1]

Другая функция, «$ZBOOLEAN(arg1, arg2, bit - op)», использует байтовое представление символов и позволяет выполнять битовые логические операции, заданные третьим аргументом, между первыми двумя. Имя функции $ZBOOLEAN не может быть сокращено.

Основные Z-функции

$ZF позволяет осуществлять вызов программ или функций, написанных на языках, отличных от Cache ObjectScript. $ZF имеет при этом общий вид:

$ZF(-1, "командная строка"[, аргументы])

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

Если аргумент является корректным десятичным значением, функция $ZHex превращает его в соответствующее шестнадцатеричное число. В ином случае аргумент рассматривается как строка, содержащая шестнадцатеричное значение, и производится попытка его преобразования в десятичное значение:

>Write $ZHex(6840) // выводит 1АВ8
>Write $ZHex(16_"H") // выводит 22

В операционных системах, поддерживающих 16-битные символы, функция $ZISWIDE(str) позволяет определить, содержит ли строка str 16-битные символы. Если да, то функция возвращает 1, в противном случае – 0. Например, $ZISWIDE ($char (71, 300)) вернет 1.

$ZLAscii и $ZWAscii, а также обратные функции $ZLChar и $ZWChar аналогичны по своему действию двум функциям $Char и $Ascii. Отличие состоит лишь в том, что функция ZLAscii оперирует с четырехбайтовыми, a $ZWAscii – с двухбайтовыми строками. Сокращения соответственно выглядят так: $ZLA, $ZWA, $ZLC и $ZWC.

Следующие примеры пояснят действие функций. Большей частью они применяются в программах перекодировки и обмена данными, когда дело доходит до преобразования двоичной информации в символы ASCII и наоборот.

>Write $ZWCHAR(25185)
ab
>Write $ZWASCII("ab")
25185
>Write $ZLCHAR(1684234849)
abcd
>Write $ZLASCII("abcd")
1684234849

Функция $ZNAME(str, n) проверяет, соответствует ли строка str соглашениям об именах Cache ObjectScript. Параметр n задает тип проверки, которую необходимо выполнить. Например, для проверки str на допустимое имя локальной переменной можно использовать значение параметра 0. Если в str содержится допустимое имя, функция вернет значение 1, в противном случае – 0. Следующая таблица содержит список допустимых значений n и тип выполняемой проверки.

Значение параметра Выполняемое действие
0 Проверка на имя локальной переменной
1 Проверка на имя программы
2 Проверка на метку
3 Проверка на имя глобальной переменной
4 Проверка на имя класса
5 Проверка на имя метода
6 Проверка на имя атрибута

Таблица 19. Значения параметра функции SZNAME.

$ZSearch (сокращенно $ZSE) — это функция, которая специфична для Windows-версий Cache. $ZSearch возвращает полный путь к файлу, имя которого (или маска) передается в качестве аргумента функции.

Функции $ZWPack(str) и $ZWBPack(str) преобразуют аргумент str в двухбайтовый символ. Поскольку str может и не содержать допустимый 16-битовый символ, необходимо для проверки использовать функцию $ZISWIDE. $ZWPack возвращает символ в так называемой little-endian форме, a $ZWBPack в big-endian форме. Функции, осуществляющие обратное преобразование –$ZWUNPack и $ZWBUNPack, соответственно.

Строковые Z-функции

Для начала рассмотрим функцию «$ZConvert(<expr>, Mode)» (сокращенно $ZCVT), существенно облегчающую работу по преобразованию прописных букв в строчные и наоборот. Режим (Mode) во втором аргументе — это «u» («U») или «l» («L»), причем в первом случае все встречающиеся строчные буквы преобразуются в прописные, а во втором — наоборот.

>Write $ZConvert("ABC123", "L") 
abc123

$ZCyc(<expr>) (сокращенно $ZC) является функцией работы с текстом лишь в том смысле, что используется при передаче данных или при взаимодействии программ для подсчета контрольных сумм, которые служат для проверки правильности передаваемого текста. Вычисление контрольной суммы происходит побитно, с использованием операции xor.

$ZSTRIP(<ехрr>, действие, удаление, сохранение) (сокращение имени не предусмотрено) в высшей степени полезна для удаления и сохранения отдельных символов или целых классов символов в заданной строке. При этом классы символов задаются в соответствии с правилами, определенными для проверки по шаблону. Несложный пример поясняет принцип действия. Из произвольной строки символов хотят удалить все цифры, кроме «7».

>Set str = "jhfgsfgl02nn7754ggiu" 
>Write $ZSTRIP(str, " * N", , "7") 
jhfgsfglnn77ggiu

Второй аргумент функции задает действие: следует удалить все N – то есть числовые символы – в то время как четвертый аргумент (третий аргумент в примере отсутствует, что показано запятыми) задает, какие символы необходимо сохранить.

$ZUtil-функции

$ZUtil (Number [, Mode [, ...]]) (кратко $ZU) определена для огромного количества числовых аргументов. С помощью этой функции можно осуществлять целый ряд совершенно различных, зачастую очень глубоких системных операций, являющихся, разумеется, частично зависимыми от платформы.

Списки

Что такое списки?

Списки — это перечни отдельных значений.

Рассмотрим следующий список:

L1 = {красный, зеленый, голубой}

L1 coстоит из трех элементов. Последовательность элементов в списке имеет значение. Список:

L11 = {зеленый, голубой, красный}

отличен от списка L1.

Список L2 = {} не содержит элементов, то есть он пуст и называется также нулевым списком. Список может содержать неопределенные элементы, как это показывает следующий пример:

L3 = {красный, зеленый, , голубой}

Третий элемент списка не определен. Заметим, что число элементов в этом списке равно 4. Далее, список L3 не эквивалентен списку

L4 = {красный, зеленый, "", голубой}, 

так как в этом списке третий элемент определен как пустая строка.

Точно так же и сам элемент списка может вновь быть списком:

L5 = {красный, {светлокрасный, оранжевый, вишневокрасный}, зеленый, голубой}

L5 содержит четыре элемента, второй из них является списком.

Списки можно соединить оператором конкатенации. В Cache для конкатенации списков используется символ подчеркивания. Следующее выражение создает список из шести элементов:

{красный, зеленый, голубой} _ {коричневый, фиолетовый, черный}

Отдельные элементы списка обычно понимаются как строки символов (исключая ситуации, когда элемент списка сам является списком). Типичные задачи при работе со списками:

Описывать списки можно в виде строки, разделяя отдельные элементы списка разделительным символом, например, косой чертой:

Set L1 = "красный/зеленый/голубой"

Выбранный разделительный символ ни при каких обстоятельствах не должен встречаться как символ ни в одном из элементов списка. Cache ObjectScript предоставляет все необходимые элементы языка для создания и управления самостоятельно определенными списками.

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

Set L1 = $ListBuild("красный", "зеленый", "голубой")

Приведем еще два примера:

Set list = "Becнa/Лeто/Oceнь/3имa"
Set address = "Петров И.П.^Калинин^192022^ул. Мира, 21, 10:65745 / 53221"

Второй пример показывает многие нюансы. Во-первых, строка символов, понимаемая как запись, представлена в форме списка с символом ^ в качестве разделителя. Далее, некоторые поля (иными словами, элементы списка) содержат подсписки, имеющие в свою очередь другие разделители, как показывает последний элемент списка, содержащий два телефонных номера.

Для управления этими списками подходят три основных элемента языка (см. также определения этих элементов языка в таблице 15):

>Write $Length(list, "/")
4
>Write $Piece(address, "^", 4)
ул. Мира, 21, 10
>Set $Piece(address, "^", 2) = "Тверь"
>Write address
Петров И.П.^Тверь^192022^ул. Мира, 21, 10^65745 / 53221

$Length возвращает «длину» списка, когда в качестве второго аргумента указывается соответствующий разделитель списка. $Piece возвращает один (или несколько) элементов списка, причем разделитель задается как второй аргумент.

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

Определение списков с помощью ListBuild

В общей сложности в Cache определено шесть функций, позволяющих ускорить обработку списков по сравнению с ручной обработкой, так как при определении списка одновременно кодируется длина, а также тип отдельных элементов. Разделительные символы при этом не применяются. Для начала опишем эти функции в таблице 20.

Списковая функция Сокр. Краткое описание
$ListBuild $LB создает списки
$ListLength $LL возвращает количество элементов списка
$LIst $LI извлекает один или несколько элементов списка
$ListGet $LG предотвращает ошибку <null value>, если заданный элемент списка неопределен; по смыслу эквивалентна $Get
$ListData $LD логическая функция, проверяющая существование элемента списка
$ListFind $LF осуществляет поиск заданного элемента списка

Таблица 20. Краткое описание списковых функций.

С помощью $ListBuild создаются списки. Далее используются списки L1-L5, описанные в начале данного раздела:

>Set L1 = $ListBuild("красный", "зеленый", "голубой") 
L1 = {красный, зеленый, голубой} 
>Set L2 = $ListBuild()
пустой список L2 = {}
>Set L3 = $ListBuild("красный", "зеленый", , "голубой")
L3 = {красный, зеленый, , голубой}
>Set L4 = $ListBuild("красный", "зеленый", "", "голубой")
L4 = {красный, зеленый, "", голубой}
>Set L5 = $ListBuild("красный", $ListBuild("светлокрасный", 
  "оранжевый", "вишневокрасный"), "зеленый", 
  "голубой")
Список, содержащий в качестве второго элемента другой список. 

Аргументы $ListBuild могут представлять собой любые выражения:

Set list = $ListBuild(2 * x1, 3 * x2)

С помощью этой команды создается список с двумя числовыми элементами.

Kill var Set list = $ListBuild(var, 1)

Ссылка на неопределенную переменную в аргументе функции $ListBuild не приводит к ошибке. В примере создается список, первый элемент которого не определен, а второй имеет значение 1.

Списки могут соединяться с помощью оператора конкатенации. Именно поэтому выражение

$ListBuild("a", "b")_$ListBuild("c")

создает список с тремя элементами "а", "b" и "с". Заметим, что выражения

$ListBuild("a", "b")
$ListBuild("a", "b")_$ListBuild()
$ListBuild("a", "b")_$ListBuild("")

представляют собой три различных списка. Первый содержит два элемента, второй три, причем третий не определен, в то время как третий список также содержит три элемента, третий из которых — пустая строка.

Как много элементов содержит список? На этот вопрос отвечает функция $ListLength.

>Write $ListLength(L1) // выводит 3
>Write $ListLength(L2) // выводит 1
>Write $ListLength(L3) // выводит 4
>Write $ListLength(L4) // выводит 4
>Write $ListLength(L5) // выводит 4

Примеры говорят сами за себя. $ListLength не распознает, является ли сам элемент списком, а лишь считает число первичных элементов списка. Таким образом, $ListLength не распознает элементы во вложенных списках.

Если в качестве аргумента используется любая строка символов, а не список, созданный $ListBuild, появляется сообщение об ошибке <list>.

Обработка списков

Один или несколько элементов списка могут выделяться с помощью функции работы со списками $LIst. Она имеет следующий общий вид:

$LI[st] (list [, position[, end]])

При этом list представляет собой созданный с помощью $ListBuild список, в противном случае возникает сообщение об ошибке <list>. В одноаргументной форме выделяется первый элемент списка. Position – это начальная позиция, начиная с которой происходит выделение. Если конечная позиция (end) не задана, выделяется один элемент списка, который далее интерпретируется как строка символов (конечно, если сам он не является подсписком). Если позиция end задана, выделяется по меньшей мере один элемент списка, интерпретируемый кроме того, как список! В этом отношении, если список L1 определен как {красный, зеленый, голубой}, то:

$LIst(L1, 2) // соответствует строке символов "зеленый" 
$LIst(L1, 2, 2) // соответствует списку {зеленый}

position и end могут иметь значение -1, представляющее собой указание на последнюю позицию списка (ее можно было получить также из выражения $ListLength(list)).

Следовательно, с помощью вызова «Set x = $List(L1, 2, -1)» получают список, состоящий из {зеленый, голубой}.

Если position равен 0, имеются две возможности:

$LIst(L1, 0) // сообщение об ошибке <NULL VALUE> 
$LIst(L1, 0, 2) // соответствует вызову $LIst(L1, 1, 2)

Если position меньше -1, получают сообщение об ошибке <RANGE>. Если значение end меньше, чем position, возвращается пустая строка. Если position больше, чем длина списка (и позиция end не указана), результатом является пустой список, то есть {}.

Если в двухаргументной форме сослаться на неопределенный элемент списка, будет выдана ошибка <null value>. В трехаргументной форме эта ошибка не возникает, поскольку в качестве результата всегда получается список.

Set L3 = $ListBuild("красный", "зеленый", , "голубой")
// ошибка <NULL VALUE>, третий элемент не определен
Write $LIst(L3, 3) 
// нет сообщения об ошибке, результатом является пустой список
Write $LIst(L3, 3, 3)

Подобно $Piece, а также $Extract, имеется так называемая левосторонняя форма $LIst, которую можно использовать для изменения одного или нескольких элементов списка. Например, ее можно применить для создания отсутствующего третьего элемента в списке L3:

Set $LIst(LЗ, 3) = "желтый"

Результатом является список {красный, зеленый, желтый, голубой}. В развитие этой возможности в список можно ввести подсписки, поместив в правой части выражения вызов функций $ListBuild или $LIst:

Set $LIst(x, pos) = $ListBuild(list) 
Set $LIst(x, pos) = $LIst(list, pos, end)

Следующая списковая функция – $ListGet – это расширение $LIst. $ListGet идентична одноаргументной и двухаргументной формам $LIst, за исключением того, что не порождает ошибки <null value>. С помощью функции $ListGet можно выделить определенный элемент из списка. Если этот элемент списка не определен, то в виде значения по умолчанию возвращается третий аргумент, если он не задан – пустая строка:

>Write $ListGet(L3, 3) // двухаргументная форма 
(пустая строка)
>Write $ListGet(L3, 3, "васильковый")
васильковый (трехаргументная форма)

Как вообще можно установить, определен элемент списка или нет? Здесь поможет функция $ListData:

$ListData(list, position)

Второй параметр этой функции задает проверяемую позицию списка. Если элемент в этой позиции определен результат функции будет 1, иначе 0.

>Write $ListData(L3, 2)
1
>Write $ListData(L3, 3)
0

Последняя функция работы со списками – $ListFind, возвращающая позицию искомого элемента списка:

>Write $ListFind(L3, "зеленый") 
2

$ListFind возвращает 0, если искомый элемент в списке не встретился. Подстроки, такие, как, например, «ый» не распознаются, так же, как и элементы подсписков. Общая форма $ListFind:

$ListFind(list, value[, position])

Поиск значения value осуществляется начиная с (необязательной) позиции position. Если position больше, чем длина списка, в качестве результата функция вернет 0.

Далее с помощью цикла For можно отыскать все места в списке, где встречается указанное значение. Предположим, у нас имеется список:

Lg = {зеленый, голубой, охра, зеленый, красный, черный, зеленый}

Следующий цикл For находит три позиции элемента «зеленый»:

>Set x = 0
>For Set x = $ListFind(Lg, "зеленый", х) Quit:x = 0 Write !, x, " ", $LIst(Lg, x)

Если значение третьего аргумента (position) меньше -1, возникает ошибка <RANGE>.


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

Copyright © 1994-2016 ООО "К-Пресс"