diff --git a/src/ch02.md b/src/ch02.md index 166487f..66fdaa9 100644 --- a/src/ch02.md +++ b/src/ch02.md @@ -642,8 +642,8 @@ try action(req, res); Довольно часто используется комбинация объединения с ошибкой с опциональным типом. Если набор ошибок выводится, то это записывается вот так: -``` -/ load the last saved game +```zig +// load the last saved game pub fn loadLast() !?Save { // TODO return null; @@ -655,7 +655,7 @@ pub fn loadLast() !?Save { извлечь ошибку и затем `orelse`, чтобы развернуть необязательное значение, вот рабочий скелет: -``` +```zig const std = @import("std"); pub fn main() void { @@ -686,5 +686,3 @@ pub const Save = struct { ещё более широкие возможности, то, что мы видели в первых двух главах, уже составляет значительную часть языка. И это будет служить нам базой при исследовании более сложных тем без отвлечения на синтаксис. - - diff --git a/src/ch03.md b/src/ch03.md index e69de29..7dfffc8 100644 --- a/src/ch03.md +++ b/src/ch03.md @@ -0,0 +1,130 @@ + +# Руководство по стилю оформления. + +В это короткой главе мы рассмотрим 2 правила оформления, +которые обеспечивабтся компилятором, а также различные +соглашения об именовании в стандартной библиотеке Zig. + +## Неиспользуемые переменные + +Zig не позволяет оставлять переменные неиспользованными. +При компиляции следующего кода мы получим 2 ошибки: + +```zig +const std = @import("std"); + +pub fn main() void { + const sum = add(8999, 2); +} + +fn add(a: i64, b: i64) i64 { + // обратите внимание, что тут a + a, а не a + b + return a + a; +} +``` + +``` +src/ex-ch03-01.zig:5:11: error: unused local constant + const sum = add(8999, 2); + ^~~ +src/ex-ch03-01.zig:8:16: error: unused function parameter +fn add(a: i64, b: i64) i64 { +``` + +Первая ошибка возникла потому, что локальная константа `sum` никак +после присваивания ей значения не используется. Вторая ошибка связана +с тем обстоятельством, что `b` (второй аргумент функции `add`) +тоже внутри функции никак не используется. Однако, у Вас могут +быть вполне уважительные причины реально иметь в своём +коде неиспользованные локальные переменные или параметры функций, +поэтому в Zig возможноть игнорировать ненужные значения +путём присваивания их символу `_`, вот таким образом: + +```zig +const std = @import("std"); + +pub fn main() void { + _ = add(8999, 2); + + // или + + sum = add(8999, 2); + _ = sum; +} + +fn add(a: i64, b: i64) i64 { + _ = b; + return a + a; +} +``` + +Вместо того, чтобы внутри тела `add` написать `_ = b;`, мы могли +бы использовать `_` в её заголовке, то есть `fn add(a: i64, _: i64) i64 {`, +однако, такой вариант менее желателен, посольку заставляет пользователя +гадать, что собой представляет параметр `b`. + +Обратите также внимание, что `std` в этом примере никак не используется, +однако, это не порождает ошибку. Возможно, в будущем Zig будет считать +это ошибкой. + +## Маскирование/затенение имён (shadowing) + +Zig не ползволяет одному идентификатору "перекрывать" собой другой, +используя то же самое имя. Следующий код для чтения из сокета не является +корректным: + +```zig +fn read(stream: std.net.Stream) ![]const u8 { + var buf: [512]u8 = undefined; + const read = try stream.read(&buf); + if (read == 0) { + return error.Closed; + } + return buf[0..read]; +} +``` + +Тут переменная `read` конфликтует с именем самой функции. + +## Соглашения об именовании + +За исключением правил, диктуемых компилятором, Вы, разумеется, +вольны использовать такие такие соглашения об именах, какие Вам больше +нравятся. Однако, соверешенно не вредно понимать собственные +соглашения Zig, поскольку стандартная библиотека, которой Вы, +безуловно, будете пользоваться, придерживается этих соглашений. + +Отступы в Zig - это 4 пробела. Как правило, текстовые редакторы +можно настроить так, чтобы клавиша `Tab` вставляла именно 4 пробела, +а не символ табуляции и это гораздо удобней, 4 раза нажимать пробел. + +Имена функций пишутся в `camelCase`, имена переменных - в `snake_case`. +Типы пишутся в `PascalCase`. Есть одно интересное перечение этих 3-х правил. +Переменные, которые хранят тип или функции, которые возвращают тип, +так же, как и сами типы, пишутся в `PascalCase`. Мы уже видели нечто подобное: + +```zig +// смотрим на встроенную функцию '@TypeOf' +std.debug.print("{any}\n", .{@TypeOf(.{.year = 2023, .month = 8})}); +``` + +Мы уже видели некторые другие встроенные функции, как то `@import`, `@rem` и `@intCast`. +Поскольку это функции, их имена записаны в `camelCase`. Однако, `@TyoeOf` это тоже +(встроенная) функция, но она почему то написана в `PascalCase`. А это потому, +что она возвращает *тип* и поэтому для её имени используется соглашение для типов, +а не для функций. Если бы присваивали результат функции `@TypeOf` какой-то переменной, +эту переменную так же следовало бы писать в `CamelCase`: + +```zig +const T = @TypeOf(3) +std.debug.print("{any}\n", .{T}); +``` + +У компилятор Zig есть команда `fmt`, которая форматирует обозначенные файлы +по своим правилам. Впрочем, такое форматирование затрагивает не всё - +например, оно подправит отступы и положение фигурных скобок для блоков, +но регистр идентификаторов останется как есть. + + + + diff --git a/src/ex-ch03-01.zig b/src/ex-ch03-01.zig new file mode 100644 index 0000000..be48328 --- /dev/null +++ b/src/ex-ch03-01.zig @@ -0,0 +1,11 @@ + +const std = @import("std"); + +pub fn main() void { + const sum = add(8999, 2); +} + +fn add(a: i64, b: i64) i64 { + // обратите внимание, что тут a + a, а не a + b + return a + a; +} diff --git a/src/ex-ch03-02.zig b/src/ex-ch03-02.zig new file mode 100644 index 0000000..e7e1429 --- /dev/null +++ b/src/ex-ch03-02.zig @@ -0,0 +1,17 @@ + +const std = @import("std"); + +pub fn main() void { + _ = add(8999, 2); + + // или + // sum = add(8999, 2); + // _ = sum; + // нет, так тоже 'error: use of undeclared identifier 'sum'' +} + +fn add(a: i64, b: i64) i64 { + _ = b; + return a + a; +} +