diff --git a/src/ch01.md b/src/ch01.md index 2102ae5..a76610b 100644 --- a/src/ch01.md +++ b/src/ch01.md @@ -218,7 +218,7 @@ pub const User = struct { const user = User{.name = "Пётр"}; ``` то мы получим ошибку, в которой будет сообщено, что поле `power` отсутствует. -Если же использовать определение, в котором для поля `power` заданом значение по умолчанию, +Если же использовать определение, в котором для поля `power` задано значение по умолчанию, то тогда такой код успешно откомпилируется. Структуры могут иметь методы, они могут содержать определения (включая другие структуры), @@ -249,3 +249,86 @@ user.diagnose(); User.diagnose(user); ``` +Что касается инструкции `if` внутри функции `diagnose`, то она вполне +самоочевидна. Мы исследуем это подробнее в следующей части. + +Итак, функция `diagnose` определена внутри типа `User` и принимает +такую же структуру в качестве своего первого и единственного параметра. +Соответственно, мы можем вызывать эту функцию, используя точку, +в "сахарном" варианте. Однако, функции внутри структуры вовсе не обязаны +следовать такому правилу. Один из распространённых примеров - это +функция инициализации: + +```zig +pub const User = struct { + power: u64 = 0, + name: []const u8, + + pub fn init(name: []const u8, power: u64) User { + return User{ + .name = name, + .power = power, + }; + } +} +``` + +Использование именно такого имени (`init`) является просто соглашением, +то есть в каких-то случаях более уместными могут показаться и другие имена, +например, `open`. Если Вы не программист на C/C++, то такой синтаксис +инициализации полей (с точкой, `.name = name`) может показаться Вам +слегка странным, но со временем Вы к этому привыкнете. + +Когда мы создавали пользователя `Пётр`, мы объявили экземпляр +`user` как константу (`const`): + +```zig +const user = User{ + .power = 9001, + .name = "Пётр", +}; +``` + +Это означает, что мы не можем модифицировать эту "переменную". +Чтобы иметь возможность модификации, нужно объявить экземпляр +при помощи ключевого слова `var`, а не `const`. Возможно, +Вы так же заметили, что тип переменной `user` выводится из того, +что в неё присваивается. Мы могли бы написать всё явно, то есть вот так: + +```zig +const user: User = User{ + .power = 9001, + .name = "Пётр", +}; +``` + +Мы ещё увидим в дальнеёшем случаи, когда явное указание типа переменной +обязательно, но в большинстве случаев код более читабелен без +явного указания типа. Вывод типов работает также и в другую сторону: + +```zig +const user: User = .{ + .power = 9001, + .name = "Пётр", +}; +``` +Впрочем, такое использование не особо употребительно. Одно из мест, +где это используется - возвращение структуры из функции, тут тип +может быть выведен из типа возвращаемого значения функции. +Более вероятно, что наша функция инициализации выглядела бы так: + +```zig +pub fn init(name: []const u8, power: u64) User { + // вместо того, чтобы возвращать User{...} + return .{ + .name = name, + .power = power, + }; +} +``` + +Как и большинство вещей, которые мы уже немного изучили, +мы рассмотрим структуры более подробно в дальнейшем. + +## Массивы и срезы +