:h1.Краткое описание
:p.
:artwork align='center' name='0001-About\Images\Veronica.bmp'.

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

:p.
Запись выражений в скобках и слева направо может показаться
странной тем, кто раньше программировал на других языках - но
именно эта запись позволяет читать их из файлов и транслировать
в байт-код с наибольшей возможной скоростью. Язык Veronica может 
быть чем-то вроде Ассемблера для языка Selene, на котором в таком
случае и были бы составлены программы - и это сочетание оказалось 
довольно удобным.

:p.
Чтобы знакомство со скобочной записью не вызывало затруднений, 
в книге есть примеры, раскрывающие особенности языка и основные 
приёмы кодирования на нём. В следующей главе они даются в двойной 
записи: на языке Veronica и на языке Selene.

.*

:h2.Несколько примеров
:p.
Самая короткая программа на Selene и Veronica выглядит так:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-1.rc'.
:font facename=default.

:p.
Как видно, она печатает строку и завершается. 

:p.
А вот так выглядит описание структуры данных:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-2.rc'.
:font facename=default.

:p.
Или так:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-3.rc'.
:font facename=default.

:p.
И действия с ней:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-4.rc'.
:font facename=default.

:p.
Как видно, здесь описана структура из 4-х байт и над ней -
функция, позволяющая читать из неё поле "brightness", вот 
так:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-5.rc'.
:font facename=default.

:p.
И на место обращения к этому полю будет подставлен вызов
функции:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-6.rc'.
:font facename=default.

:p.
Так что команда "say" напечатает рассчитанное (в данном 
случае - нулевое) значение.

:p.
В следующем примере выполняется расчёт взвешенного среднего 
по массиву или списку:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-7.rc'.
:font facename=default.

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

:p.
Вызов этой функции (и расчёт взвешенного среднего) в языке 
Selene выглядит так:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-8.rc'.
:font facename=default.

:p.
А в языке Veronica - вот так:
 
:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-9.rc'.
:font facename=default.

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

:p.
В следующем примере - цикл с двумя счётчиками, который
выполняет разворот квадратной матрицы относительно её 
главной диагонали:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-A.rc'.
:font facename=default.

:p.
А здесь - цикл с условиями:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-B.rc'.
:font facename=default.

:p.
Этот цикл будет выполняться до тех пор, пока функция 
"lines()" в его заголовке будет возвращать единицу, а
когда она вернёт нулевое значение - цикл завершится.

:p.
В следующем примере - разворот массива:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-C.rc'.
:font facename=default.

:p.
И разворот списка с помощью рекурсии:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-D.rc'.
:font facename=default.

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

:p.
Просмотр дерева каталогов:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-E.rc'.
:font facename=default.

:p.
Здесь рекурсивная функция обходит дерево и вызывает себя
же (с именем каталога) или внешнюю функцию (с именем файла).
Эта задача примечательна тем, что расход памяти в ней зависит 
от глубины дерева каталогов, но не зависит от количества файлов
в них: она требует "O(1)" памяти вне зависимости от того, сколько 
файлов было записано в каталогах внутри дерева.

:p.
Подсчёт частоты встречаемости слов в тексте:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-F.rc'.
:font facename=default.

:p.
Эта задача требует приблизительно "O(n*log2(n))" памяти 
в зависимости от количества слов в строке. В ней, как 
и в примерах выше, используется приём с заполнением 
переменной, содержащей пустое значение, и закрытием её 
от дальнейших изменений.

:p.
Быстрая сортировка:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-G.rc'.
:font facename=default.

:p.
Быстрая сортировка требует "O(n*log(n))" действий, а расход 
памяти в ней стремится к "O(n^2)", поскольку на каждом шаге 
создаются два новых списка. Тем не менее, эта сортировка - 
действительно одна из самых быстрых: у многих сортировок 
время работы и расход памяти стремятся к "O(n^2)".

:p.
Следующий пример - команда "expect", позволяющая выполнять 
регрессионные тесты:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-H.rc'.
:font facename=default.

:p.
В данном случае эта команда ждёт, что функция "average()"
выполнит команду "exit" с параметром "ERR_*" и завершится.
В таком случае тест считается пройденным - и это так и 
задумано.

:p.
Доопределение вызываемой функции двумя безымянными 
функциями в языке Selene:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-I.rc'.
:font facename=default.

:p.
И в языке Veronica:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-J.rc'.
:font facename=default.

:p.
В данном случае это получение Web-страницы и проверка 
HTTP-кода от Web-сервера. Точно так же выглядит расчёт
взвешенного среднего в одном из примеров выше.

:p.
Отправка запросов к СУБД и обработка исключений:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Syntax-K.rc'.
:font facename=default.

:p.
Если здесь произойдёт ошибка, будет вызвана команда "log" 
и функция "handle()", а затем выполнение будет продолжено 
со следующей строки после обработчика ошибок. В переменной
"alarm" останется код ошибки, который позже будет проверен 
в операторе условия, чтобы выполнить одну из двух команд 
"log".

.*

:h2.Состояние программы
:p.
Довольно важная особенность языка Veronica - запрет на 
создание глобальных переменных:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\State-1.rc'.
:font facename=default.

:p.
И вместо того, чтобы объявлять структуру "state", где будет
записано состояние программы, в её заголовке, надо объявить
и создать её в точке вызова функции "msg-in()", вот так:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\State-2.rc'.
:font facename=default.

:p.
Теперь структура "state" будет передаваться от одной функции
к другой:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\State-3.rc'.
:font facename=default.

:p.
И будет изменяться внутри безымянной функции, переданной на 
вход функции "msg-in()", вот так:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\State-4.rc'.
:font facename=default.

:p.
И в дополнение к тому, что во всех функциях она будет видна
с правами доступа только на чтение, все её изменения будут 
сосредоточены в одном месте.

.*

:h2.Данные в памяти
:p.
Структуры данных, расположенные в памяти, должны быть связаны
таким образом, чтобы из них получилось дерево:
.br
:artwork align='center' name='0001-About\Images\Relations-1.bmp'.
.br
Оно так и называется: дерево структур данных. Когда на структуру
создаётся несколько ссылок, она временно закрывается от изменений,
а циклические ссылки - запрещены:
.br
:artwork align='center' name='0001-About\Images\Relations-2.bmp'.
.br
Отказ от перекрёстных и циклических ссылок ведёт к тому, что 
действия с одним и тем же типом данных оказываются расположены 
в одном месте (включая доступ на чтение).

.*

:h2.Запись выражений
:p.
В языке Veronica применяется запись выражений слева направо,
когда первым задаётся действие, а последним - переменная, где
должен оказаться результат:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Control-1.rc'.
:font facename=default.

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

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Control-2.rc'.
:font facename=default.

:p.
Некоторые действия, в том числе вычитание и деление, требуют
ещё пары скобок:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Control-3.rc'.
:font facename=default.

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

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\Control-4.rc'.
:font facename=default.

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

.*

:h2.Поток выполнения
:p.
В отличие от многих других языков программирования, в языке
Veronica все функции должны быть записаны под одним и тем же 
правилам:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\ControlFlow-1.rc'.
:font facename=default.

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

:p.
Так, в следующем примере функция, рассчитывающая факториал, 
записана правильно:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\ControlFlow-2.rc'.
:font facename=default.

:p.
И здесь:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\ControlFlow-3.rc'.
:font facename=default.

:p.
А в этом примере она записана с ошибкой:

:p.
:font facename=Courier.
:include mode='code' file='0001-About\Include\ControlFlow-4.rc'.
:font facename=default.

:p.
Из-за того, появление операторов условия до вычислений 
или возврат из середины функции (как и записано в этом 
примере) считается ошибкой.

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

.*

:h2.Почти как язык Ассемблера
:p.
Да, всё верно, Veronica может работать как язык Ассемблера, 
в который транслированы выражения на языке Selene.

:p.
Так и задумано.