Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Предопределенные структуры (Int, Real, String, Unit)

Целые числа (libretto/Int)

Целые числа представлены структурой libretto/Int. Такие числа не имеют ограничения разрядности (в JVM представлены java.math.BigInteger). Разрядность растёт по мере увеличения числа. Числа могут быть как положительные, так и отрицательные, нуль строго 0 без знака.

Поддерживаются операции, которые тоже дают в результате Int: + (сложение), - (вычитание), * (умножение), idiv (целочисленное деление). При выполнении этих операций нет переполнения разрядности.

При использовании операции div (обычное деление) результатом будет Real, а не Int (см. описание Real).

Целые десятичные числа Int представляются литералами, содержащими цифры от 0 до 9 без префикса.

Целые двоичные числа Int представляются литералами, содержащими цифры 0 и 1 с префиксом 0b

Целые шестнадцатеричные числа представляются литералами, содержащими цифры от 0 до F с префиксом 0x. Цифры могут быть представлены как в нижнем (a-f), так и в верхнем (A-F) регистре.

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

Пример:

def main = {
  println: 1234567
  println: 1_2_3_4_5_6_7
  println: -0x1_0
  println: 0x1000000
  println: 0x1_000_000
  println: -0b11
  println: 0b1111111111111111
  println: 0b1111_1111_1111_1111
}

Выдает:

1234567
1234567
-16
16777216
16777216
-3
65535
65535

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

def main = {
  fix i1: Int = -1_23.4567e4
  fix i2: Int = 1234000E-3
  println: i1
  println: i2
}

Выдает:

-1234567
1234

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

Вещественные числа (libretto/Real)

Вещественные числа представлены структурой libretto/Real. Такие числа при обычном использовании (за исключением деления div) не имеют округления и ограничения разрядности (в JVM представлены java.math.BigDecimal). Числа могут быть как положительные, так и отрицательные.

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

def main = {
  println: 0.1 + 0.2
}

Выдает: 0.3

Операции +, -, * не ограничивают разрядность результат и не делают округлений (MathContext.UNLIMITED). Поэтому при таких вычислениях разрядность может возрастать, что приведёт к замедлению вычислений и увеличению потребляемой памяти.

При делении div разрядность ограничена (MathContext.DECIMAL128 - IEEE 754R Decimal128, 34 десятичные цифры). Это же происходит при обычном делении (div) целых чисел Int: сперва они преобразуются в Real без ограничений, а затем производится деление с указанным ограничением.

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

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

def main = {
  println: 3.14_15_92_6
}

Выдает: 3.1415926

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

def main = {
  fix r1: Real = -1.23456e3
  fix r2: Real = 1_000_001E-7
  println: r1
  println: r2
}

Выдает:

-1234.56
0.1000001

Строковое представление вещественного числа может быть в экспоненциальной записи. Для получения строкового представления без экспоненты можно использовать метод libretto/util/plainString

use libretto/util

def main = {
  fix r: Real = 0.1000001 div 1000000000
  println: r
  println: r.util/string
  println: r.util/plainString
}

Выдает:

1.000001E-10
1.000001E-10
0.0000000001000001

Если нужна скорость или экономия памяти, то возможно использование вещественных чисел с ограниченной разрядностью из пакета libretto/num.

Строки и символы (libretto/String)

Строки свободной длины представлены структурой libretto/String. В строках допускается использование символов Unicode, в том числе с кодами больше 0xFFFF.

Базовый строковый литерал использует двойные кавычки ", внутри допускается использование экранирования символов при помощи \:

  • \\ - символ \
  • \" - символ "
  • \' - символ '
  • \r - символ CARRIAGE RETURN с кодом 0x0D
  • \n - символ LINE FEED с кодом 0x0A
  • \b - символ BACKSPACE с кодом 0x08
  • \t - символ табуляции с кодом 0x09
  • \f - символ FORM FEED с кодом 0x0С

Можно указывать символ при помощи кода (Unicode) двумя вариантами:

\uABCD, где ABCD - это строго четыре шестнадцатеричные цифры кода символа \{ABCDE}, где ABCDE - это любое число шестнадцатеричных цифр кода символа

def main = {
  println("\u0041\u0042\u0043")
  println("\u{41}\u{42}\u{43}")
  println("\u{1f603}")
}

Выдает:

ABC
ABC
😃

Строка без экранируемых символов определяется при помощи пары << и >>, допускается использовать символы с любыми кодами (в том числе переносы строк:

def main = {
  print(<<a
b
c
>>)
}

Выдает:

a
b
c

Нет явного типа для представления отдельных символов. Для этого используется строка (String), но содержащая один символ (Unicode codepoint, если говорить более строго).

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

def main = {
  fix str = "Hello! \u{1f603}"
  println: str.chars.*size
  println: str.chars  
}

Выдает:

8
(H,e,l,l,o,!, ,😃)

todo добавить про обратную сборку join?