Skip to content

Latest commit

 

History

History
289 lines (215 loc) · 14.6 KB

ch-01-print-hello.md

File metadata and controls

289 lines (215 loc) · 14.6 KB

Привет, Zig!

Простейшая программа выглядит следующим образом:

pub fn main() void {
   
}

Эта программа не делает ничего - просто работает. Обратите внимание, что мы написали. Это функция с именем 'main". Под функцией понимается набор инструкций, которые что-либо делают и этот набор имеет имя.

Разберём синтаксис. "public" - это сокращение от английского слова "public" - публичный, открытый. "fn" - это сокращение от английского слова "function" - функция. Далее пишем имя "main". Круглые скобки обозначают блок, который может содержать входные параметры функции. Далее следует возвращаемый тип данных. Далее следует блок фигурных скобок, в котором могут находиться операторы и выражения.

Функция "main" является главной функцией. Именно её содержимое выполняется при запуске программы.

Для проверки работы программы вам не понадобиться ничего устанавливать на компьютер. Достаточно перейти на страничку https://codapi.org/zig/, втавить в поле ввода код программы и нажать кнопку "Run". Результат работы программы будет отображён в нижней части экрана. codapi.org/zig/

Итак, напишем программу, которая печатает в терминальную строку текст.

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 сообщил бы об ошибке, требуя уникальности имён функций в одном пространстве имён.

Шаблон std.debug.print

В языке 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-арта.

2 + 2 = 4 ?

Кроме строк и чисел, в 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.