The Libretto Programming Language

Libretto для веб-приложений

01 Начало работы
02 Как изучать примеры
03 Имена в Libretto
04 Типы данных
05 Операторы
06 Пути
07 Методы
08 Статическая утиная типизация

04 Типы данных

Базовые структуры данных

К базовым структурам данных относятся строки String, целые числа Int, вещественные числа Real, а также структура Unit с единственным элементом unit.

Строки String

Libretto работает только в кодировке Unicode. Libretto предлагает несколько вариантов предствления строк.

Например,

"Всем привет!\n"
В обычных строках можно использовать стандартные символы эскейпинга:

\n line feed
\r return
\t horizontal tab
\\ backslash
\" double quote
\b backspace
\f form feed
а также Unicode–представление символов.

"\u00A9" эквивалентно "©"

Иногда строки состоят только из имени или идентификатора, например, "Hello". Для таких строк Libretto предлагает более компактное представление с использованием открывающей одинарной кавычки:

'John    'a_123

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

Скобочные строки заключаются в открывающую '«' и закрывающую '»' французские кавычки. Вместо них можно также использовать двойные символы '<<' и '>>'.

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

<<
<<Здравствуй>>, сказал я.
<<Привет>>, грустно ответил она.
«Отчего такое "веселое" настроение?», спросил я.
>>

Эскейпинга для скобочных строк не предусмотрено.

Если в строку включен блок #{<выражение на Libretto>}, то это выражение может оцениваться с помощью оператора "восклицательный знак" !. Например,

"2 + 2 = #{2+2}"! == "2 + 2 = 4"

Следующие строки равны между собой

"Planet"   'Planet   <<Planet>>   «Planet»

Базовые операции на строках

На строках определены стандартные операции сравнения ==, !=, >, <, >=, <=.

Со строками работает целая группа библиотек, например,

и другие.

Целые числа Int

Могут быть положительными и отрицательными, и иметь любую длину.

1 -115 123798427349824729183471234123874291872934712934712938471298347

Базовые операции на целых числах:

На целых числах также определены стандартные операции сравнения ==, !=, >, <, >=, <=.

Вещественные числа Real

В Libretto используются вещественные числа с плавающей точкой:

-1.23    3.14159265358979323846264338327950288419716939937510

Базовые операции на целых числах:

На вещественных числах также определены стандартные операции сравнения ==, !=, >, <, >=, <=.

Структура Any

Any – структура "всех объектов". Любой экземпляр любой структуры является также экземпляром Any.

Структура Unit

Структуру Unit представляет только один элемент (экземпляр) – unit. Он используется в ситуациях, когда нужно вернуть значение, но неважно какое. Например, unit играет роль истины в предикатах (роль лжи исполняет пустая последовательность ()):

unit также играет роль контекста в тех выражениях, у которых контекст явно не определен (см. пункт Пути):

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

Последовательности

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

(1,2,3,4,5)
("abc", 4, 3.14, "hello!")

Последовательности в Libretto плоские – они не могут быть вложены друг в друга. Следующих три выражения равны последовательности (1,2,3,4,5):

(1, (2, 3), (4, 5)) == ((((1,2),3),4),5) == (1,2,3,4,5)

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

Пример с факториалом в начале также основан на этой особенности Libretto.

Элемент и одноэлементная последовательность в Libretto не отличаются:

(10) == 10
Это означает, что отдельный элемент также является частным случаем последовательности.

Пустая последовательность – последовательность (), не содержащая ни одного элемента.

Кардинальности

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

Что такое тип данных Libretto

Кардинальности вместе с именами структур определяют в Libretto типы данных. Примеры типов данных:

Пользовательские структуры

Разработчик может определить собственные структуры данных, например,

В этом примере определяется структура Person с двумя полями – name и surname. В методе main создается экземпляр структуры "Персона" для Александра Македонского, а затем берется значение его поля name.

Структуры в Libretto – неизменяемые. Однажды заданные значения полей изменить нельзя. Для хранения изменяемых значений используются мэпы.

Мэпы

"Мэп" – абстрактная структура, хранящая данные в виде пар "ключ / значение". Для задания и получения значений ключей используется метод "!". И ключом, и значением может быть любая структура Libretto.

Примеры работы с ключами из значениями мэпов:

struct Person(name:String!, age:Int!)

// присваивание значений ключам

map!'name = 'Маша
map!'age = 16
map!'Маша = Person('Маша, 16)
map!'sisters = ('Даша, 'Глаша)

fix sasha = Person('Саша, 20)
map!sasha = 'Петров

// получение значений

map!'name // == 'Маша
map!'age // == 16
map!'Маша // == Person('Маша, 16)
map!sasha // == 'Петров
map!'sisters // == ('Даша, 'Глаша)

map.keys // = ( 'name, 'age, 'Маша, Person('Саша, 20) )
map.new // новый мэп того же типа, что и map
Методы, действующие на мэпах

В Libretto имеется несколько реализаций мэпов. В веб-разработке в основном используются мэпы, реализованные в библиотеках

Существенным качеством мэпов является бестиповость: любому ключу можно присвоить любое количество любых структур:

map!'mix = (1, 'Маша, Person('Маша, 16), 3.14)

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

Опишем родственников:

В примере определены три персоны – Пол, Энн и Мэри. Энн – жена Пола, а Мэри – сестра Энн. Программа узнает, кто является свояченицей (сестрой жены) Пола.

Здесь

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

Определение типизированных методов wife, sister и name позволило нам очень компактно записать решение задачи.

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

map.to(key, value)  // ключ key в мэпе map получает значение value
Благодаря синтаксическому сахару это можно также записать так:
map {key to value}
Использование метода to позволяет нам записать программу в существенно более компактном и читабельном виде:

Для удаления ключа, достаточно присвоить ему пустую последовательность

Структуры – объединения

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

struct Number = Int | Real

def main = {
  var x: Number = 1
  x = 3.14
}
Переменной x можно задавать как целые, так и вещественные значения.

В следующем примере структура Node объединяет две реализации мэпов – из библиотек com/teacode/map и com/teacode/base. Благодаря этому метод getmap может работать как с обычными мэпами, так и с мэпами в базах данных.

Программа работает как с обычными мэпами map1 и map2, так и с объектами дефолтной базы данных Libretto.

Методы управление базой данных:

XML и HTML

Структуры XML являются примером пользовательских структур. Они определены в системной библиотеке libretto/xml. Особенностью этих структур является то, что для них в рамках Libretto предусмотрен специальный синтаксис. Например,

Эта запись эквивалентна следующей записи с явным использованием структур из libretto/xml:

В обеих программах вычисляются значения поля attrs (это атрибуты), у которых, в свою очередь, берется имя name.

XML–выражения могут быть параметризованы с помощью вставок вида #{<выражение Libretto>}. Например,

В данном примере последовательность фамилий была развернута в неупорядоченный список HTML. Здесь string – метод, возвращающий строковое представление структуры.

В Libretto может быть представлен произвольный XML. Например, можно описать виды растений:

def main = 
<CATALOG>
  <PLANT>
    <COMMON lang="en">Bloodroot</COMMON>
    <COMMON lang="ru">Лапчатка</COMMON>
    <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
    <ZONE>4</ZONE>
    <LIGHT>Mostly Shady</LIGHT>
    <PRICE>2.44</PRICE>
    <AVAILABILITY>031599</AVAILABILITY>
  </PLANT>
  <PLANT>
    <COMMON lang="en">Marsh Marigold</COMMON>
    <COMMON lang="ru">Калужница болотная</COMMON>
    <BOTANICAL>Caltha palustris</BOTANICAL>
    <ZONE>4</ZONE>
    <LIGHT>Mostly Sunny</LIGHT>
    <PRICE>6.81</PRICE>
    <AVAILABILITY>051799</AVAILABILITY>
  </PLANT>
</CATALOG>
Однако в первую очередь xml используется для формирования компонент html страниц.

Html страницы и их компоненты представляются в Libretto в строгом xml формате.

В частности, это означает, что каждому открывающему тегу должен соответствовать закрывающий (например, абзац <p>...</p>), а элементы без контента должны закрываться косой чертой в конце, например,

03 Имена в Libretto /// 05 Операторы