Menu

Zero Primitive Types: целые, числа с плавающей точкой, Bool, String, Void

Встроенные типы, которые Zero даёт из коробки: знаковые и беззнаковые целые любых разрядностей, плавающие, булевы, символы, строки и пустой тип Void.

Встроенные типы

Zero даёт маленький регулярный набор примитивных типов. Ничего экзотического, ничего удивительного — только те, что нужны каждому системному языку, и названы они согласованно.

СемействоТипыЗаметки
Знаковые целыеi8, i16, i32, i64Дополнительный код.
Беззнаковые целыеu8, u16, u32, u64Только 0 и положительные.
Размера указателяusize, isizeРазрядность совпадает с указателем платформы.
Плавающиеf32, f64IEEE-754.
Булевbooltrue или false.
СимволcharОдин скаляр Unicode.
СтрокаStringUTF-8 строка.
ПустойVoid«Нет полезного значения».

Это полный список примитивов, которыми вы будете пользоваться каждый день. Составные типы — shapes, enums, choices — строятся из них.

Целые

Целочисленные типы следуют единообразному шаблону именования: i для знаковых, u для беззнаковых, дальше — разрядность. То есть i32 — это 32-битное знаковое целое; u8 — беззнаковый байт; i64 — 64-битное знаковое.

let small_signed: i8   = -120
let byte:         u8   = 250
let id:           i32  = 1
let big:          i64  = 9_000_000_000
let index:        usize = 0

По умолчанию для литерала без суффикса — i32, если только окружающий контекст не вынуждает иное:

let answer = 42       // i32

Когда нужна конкретная разрядность, прикрепите суффикс к литералу или аннотируйте привязку:

let byte = 250_u8     // типизированный литерал
let byte: u8 = 250    // типизированная привязка

Обе формы дают одно и то же значение. Форма с суффиксом литерала удобна, когда вы передаёте литерал напрямую в функцию или строите структуру:

let pair: BytePair = Pair { left: 1_u8, right: 2_u8 }

Когда какая разрядность

Короткое правило:

  • i32 для большинства знаковой арифметики. Достаточно широк почти для всего, что вы считаете; быстрый на всех платформах.
  • u8 для байтовой работы. Байты из файла, байты в буфере, байты по сети.
  • u32 / u64 для неотрицательных счётчиков, когда важен диапазон. Смещения в файле больше 2 ГБ, большие счётчики.
  • usize для размеров и индексов. Размером с указатель — совпадает с тем, что платформа использует для адресации памяти.
  • i64 для времени-с-эпохи и подобного. Достаточно большой для наносекунд на сотни лет.

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

Булевы

let ok = true
let done: bool = false

У bool ровно два значения: true и false. Это литералы, а не константы, которые откуда-то импортируют. Условие в if или while — это bool; никакой неявной truthiness для целых или строк.

if ok {
    check world.out.write("yes\n")
} else {
    check world.out.write("no\n")
}

If/else разбирает условия подробно.

Плавающие

f32 и f64 — это 32-битные и 64-битные IEEE-754 числа с плавающей точкой соответственно. Используйте их, когда нужны дробные значения — измерения, отношения, геометрия. Для точной арифметики над деньгами предпочитайте целые в наименьшей единице (центы, сатоши), а не плавающие.

let ratio: f32 = 0.5
let pi:    f64 = 3.141592653589793

f64 — это умолчание для литералов плавающих без суффикса.

Символы и строки

char содержит одно скалярное значение Unicode:

let initial: char = 'Z'

String — это последовательность символов, обычно закодированная в UTF-8 стандартной библиотекой. Строковые литералы используют двойные кавычки:

let message: String = "hello from zero\n"

Привычные escape-последовательности работают — \n для перевода строки, \t для табуляции, \\ для литерального обратного слэша, \" для литеральной двойной кавычки.

let multi_line = "line one\nline two\n"

Стандартная библиотека выставляет байтовые представления строки для низкоуровневой работы. Форма std.mem.span("zero") возвращает Span<u8> по байтам — пригодится, когда вы парсите, хэшируете или сравниваете по байтам.

Void

Void — это «нет полезного возвращаемого значения» в Zero. Функции, существующие ради побочных эффектов, его используют:

pub fun main(world: World) -> Void raises {
    check world.out.write("hello\n")
}

main что-то пишет и возвращается. Значения отдавать обратно нечего, поэтому тип — Void. Void встретится у большинства функций, которые трогают World — их выбирают за эффект, а не за результат.

Подчёркивания в числовых литералах

Длинные числовые литералы могут использовать подчёркивания как визуальные разделители. Компилятор их игнорирует, поэтому это чисто читательская фича:

let big   = 9_000_000_000_i64
let bytes = 1_048_576_u32     // 1 MiB

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

Шпаргалка по типизированным суффиксам литералов

СуффиксТипПример
_i8 / _i16 / _i32 / _i64Знаковое целое127_i8
_u8 / _u16 / _u32 / _u64Беззнаковое целое255_u8
_usize / _isizeРазмера указателя0_usize
_f32 / _f64Плавающее0.5_f32

Тянитесь к ним, когда конструируете значение там, где окружающий контекст не фиксирует тип.

Дальше: функции

Примитивы бесполезны без того, что с ними делать. Следующая статья разбирает функции в Zero — как их объявлять, возвращать из них значения и собирать вместе для построения настоящих программ.

Часто задаваемые вопросы

Какие примитивные типы есть в Zero?

Zero поставляется со знаковыми целыми i8, i16, i32, i64; беззнаковыми u8, u16, u32, u64; целыми размера указателя usize и isize; плавающими f32 и f64; bool; char; String; и Void для функций, не возвращающих ничего полезного.

Какой тип целых по умолчанию в Zero?

Целочисленный литерал без суффикса вроде 42 по умолчанию имеет тип i32, если контекст не вынуждает другой тип. Чтобы использовать конкретную разрядность, пишите литерал с суффиксом 42_u8 или 42_i64, либо аннотируйте тип привязки явно: let count: u8 = 42.

Есть ли в Zero отдельный строковый тип?

Да. Строковые литералы вроде "hello" имеют встроенный строковый тип, который стандартная библиотека трактует как последовательность байт (обычно UTF-8). Для низкоуровневой работы с байтами библиотека выставляет span и байтовые утилиты; для посимвольных операций есть char для отдельных скалярных значений.

Что означает Void в Zero?

Void — это возвращаемый тип функции, которая не производит полезного значения. Она существует ради побочных эффектов. Привычная сигнатура pub fun main(world: World) -> Void raises использует Void, потому что main существует, чтобы делать I/O и выйти, а не чтобы производить значение.

В чём разница между i32 и u32 в Zero?

i32 — знаковое 32-битное целое с диапазоном от −2 147 483 648 до 2 147 483 647. u32 — беззнаковое с диапазоном от 0 до 4 294 967 295. Знаковые типы — когда отрицательные значения имеют смысл, беззнаковые — когда отрицательное было бы багом: для счётчиков, индексов, размеров и так далее.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ