Простейшая программа выглядит следующим образом:
pub fn main() void {
}
Эта программа не делает ничего - просто работает. Обратите внимание, что мы написали. Это функция с именем 'main". Под функцией понимается набор инструкций, которые что-либо делают и этот набор имеет имя.
Разберём синтаксис. "public" - это сокращение от английского слова "public" - публичный, открытый. "fn" - это сокращение от английского слова "function" - функция. Далее пишем имя "main". Круглые скобки обозначают блок, который может содержать входные параметры функции. Далее следует возвращаемый тип данных. Далее следует блок фигурных скобок, в котором могут находиться операторы и выражения.
Функция "main" является главной функцией. Именно её содержимое выполняется при запуске программы.
Для проверки работы программы вам не понадобиться ничего устанавливать на компьютер. Достаточно перейти на страничку https://codapi.org/zig/, втавить в поле ввода код программы и нажать кнопку "Run". Результат работы программы будет отображён в нижней части экрана.
Итак, напишем программу, которая печатает в терминальную строку текст.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.print("Hello, world!\n", .{});
}
Перейдя по ссылке, вы перейдёте в среду разработки Rust Playground и, нажав кнопку "Run", сможете посмотреть, на результат работы программы.
А теперь разберём синкаксис этот программы шаг за шагом, символ за символом:
Конечно, давайте разберем этот код построчно:
const std = @import("std");
- Эта строка импортирует стандартную библиотеку Zig, называемую
std
, которая предоставляет множество полезных функций и типов данных для работы с вводом-выводом, строками, коллекциями и другими базовыми операциями.
pub fn main() !void {
pub
делает функциюmain
доступной вне этого файла, то есть публичной.fn
обозначает определение функции.main
— это имя функции. В Zig, как и во многих других языках, функцияmain
является точкой входа программы.!void
означает, что функция возвращает либоvoid
(ничего), либо ошибку. В Zig!
перед типом указывает, что функция может завершиться ошибкой, и в этом случае она возвращает объект ошибки.
const stdout = std.io.getStdOut().writer();
const
определяет константу (переменную, значение которой не меняется) с именемstdout
.std.io.getStdOut()
вызывает функцию из стандартной библиотеки, которая возвращает объект, представляющий стандартный поток вывода (обычно — консоль)..writer()
возвращает объект для записи в поток выводаstdout
. Этот объект предоставляет методы для записи текста и данных в стандартный вывод.
try stdout.print("Hello, world!\n", .{});
try
пытается выполнить операцию и автоматически завершитmain
с ошибкой, если возникнет проблема с выводом.stdout.print
вызывает методprint
на объектеstdout
. Методprint
выводит текст в консоль."Hello, world!\n"
— строка, которая будет выведена.\n
— это символ новой строки..{}
— пустой список аргументов.print
поддерживает форматирование строк с использованием плейсхолдеров, и если дополнительных аргументов для замены плейсхолдеров нет, необходимо указать пустой массив.
Язык Zig также чувствителен к регистру символов, поэтому, например, имена функций print
, prInt
, pRint
, Print
и так далее будут считаться разными функциями. Это значит, что Zig различает функции в зависимости от заглавных и строчных букв в их именах.
Запустите следующий код в среде разработки, и, следуя сообщениям компилятора, вы сможете лучше понять, как Zig относится к именам функций и к стилю написания кода.
Вот пример программы на Zig, демонстрирующий этот аспект:
const std = @import("std");
fn print() void {
std.debug.print("print\n", .{});
}
fn prInt() void {
std.debug.print("prInt\n", .{});
}
fn pRint() void {
std.debug.print("pRint\n", .{});
}
fn Print() void {
std.debug.print("Print\n", .{});
}
fn PRInt() void {
std.debug.print("PRInt\n", .{});
}
pub fn main() void {
print();
prInt();
pRint();
Print();
PRInt();
}
- В коде объявлено несколько функций с разными сочетаниями заглавных и строчных букв.
- В каждой функции вызвана
std.debug.print
, которая выводит текст в консоль. - В функции
main
вызываются все функции, чтобы продемонстрировать, что Zig различает их по регистру.
При запуске этой программы каждая функция выведет в консоль своё имя. Если бы функциям были присвоены одинаковые имена, компилятор Zig сообщил бы об ошибке, требуя уникальности имён функций в одном пространстве имён.
В языке Zig для вывода текста на консоль используется std.debug.print
, который, аналогично макросу println!
в Rust, позволяет выводить текст с возможностью форматирования. Текстовые данные могут содержать специальные конструкции {}
, обозначающие позиции для подстановки значений, передаваемых как параметры.
const std = @import("std");
pub fn main() void {
std.debug.print("Привет, Zig!\n", .{});
std.debug.print("{}{}{}{}{}\n", .{"Привет", ",", " ", "Zig", "!"});
}
При запуске этой программы на консоли появятся две одинаковые строки. В первом вызове std.debug.print
используется простой вывод, а во втором — шаблон с подстановочными местами {}
, куда передаются значения, которые заменяют эти места по порядку.
Важной особенностью Zig является строгая проверка количества аргументов, передаваемых для форматирования. Если количество аргументов и мест подстановки не совпадает, компилятор Zig выдаст сообщение об ошибке, и программа не запустится. Попробуйте изменить количество параметров или позиций {}
и посмотрите на сообщения компилятора — это поможет лучше понять работу std.debug.print
.
Теперь, используя эти знания, создадим таблицу умножения:
const std = @import("std");
pub fn main() void {
std.debug.print(
"\t2\t3\t4\t5\t6\t7\t8\t9\n",
.{},
);
std.debug.print(
"---------------------------------------------------\n",
.{},
);
for (std.math.intRange(2, 10)) |i| {
std.debug.print("{}|\t", .{i});
for (std.math.intRange(2, 10)) |j| {
std.debug.print("{}\t", .{i * j});
}
std.debug.print("\n", .{});
}
}
Этот код выводит таблицу умножения от 2 до 9. Используется цикл для чисел, и каждое значение выводится с помощью std.debug.print
, что позволяет точно настроить формат вывода на консоль.
С помощью std.debug.print
можно даже нарисовать ASCII-арт, например, котика.
const std = @import("std");
pub fn main() void {
std.debug.print(
"
/> フ
| + +|
/`ミ _x 彡
/ |
/ ヽ ノ
/ ̄| | | |
| ( ̄ヽ__ヽ_)_)
\二つ
\n",
.{},
);
}
При запуске этого кода в консоль выведется котик. В Zig также можно использовать многострочные строки, что упрощает создание ASCII-арта.
Кроме строк и чисел, в Zig можно работать с логическими значениями. Посмотрим пример вычисления и проверки результата:
const std = @import("std");
pub fn main() void {
std.debug.print("{} + {} = {} - {}\n", .{2, 2, 2 + 2, (2 + 2 == 4)});
std.debug.print("{} + {} = {} - {}\n", .{2, 2, 5, (2 + 2 == 5)});
}
Этот код выводит результаты сложения и проверяет равенство. Логические значения отображаются в виде true
или false
.
Чтобы сделать код более читаемым, длинные строки в Zig можно разбивать:
const std = @import("std");
pub fn main() void {
std.debug.print(
"++++++++++++++++++++++++++++++\
++++++++++++++++++++++++++++++\
++++++++++++++++++++++++++++++\
++++++++++++++++++++++++++++++\n",
.{},
);
}
Здесь символ \
помогает разделить строку на несколько строк кода, но при выводе она будет отображаться как одна длинная строка.
Комментарии в Zig помогают пояснять код и могут быть однострочными и многострочными. Однострочные комментарии начинаются с //
, а многострочные — с /*
и завершаются */
.
/* Это /* синтаксически правильные */
комментарии, даже /* если они /* вложены */ */ друг в друга. */
const std = @import("std");
pub fn main() void {
std.debug.print("Hello, Zig!\n", .{});
}
Вложенные комментарии поддерживаются, но для удобства не рекомендуется слишком углублять их вложенность.
Создайте интересную программу, используя числа, строки, символы и логические значения. Например:
const std = @import("std");
pub fn main() void {
std.debug.print(
"
/_/ (•-•) /つ🌷 хочешь цветочек?
/__/ (•-•) /つ🍪 или печеньку?
/_/ (•-•) / >🐈 может кису?
/__/ (•-•) /つ❤ или моё сердечко?
(\\__(\\ ('•֊ •') O❤O думаю, это то, что надо.\n",
.{},
);
}
Или попробуйте создать другую ASCII-картинку или инфографику:
const std = @import("std");
pub fn main() void {
std.debug.print(
"
\t Изучаем печать на консоль \n
------------------------
Числа\tСтроки\tСимволы
⚙\t⚙\t⚙\n
⚙\tZig типы данных\t⚙\n
⚙\t⚙\t⚙\n
\tЛогика
",
.{},
);
}
Придумайте свои примеры, чтобы лучше понять, как работает форматирование и вывод данных в Zig.