Предопределенные структуры (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?